[comp.lang.c] Getchar w/wout echo

daveh@marob.MASA.COM (Dave Hammond) (08/20/88)

Newsgroups: comp.lang.c
Subject: Re: Re: Echoing chars and input functions
References: <8808160751.aa03016@SMOKE.BRL.MIL> <5940003@hpcupt1.HP.COM>
Reply-To: daveh@marob.masa.com (Dave Hammond)

In article <5940003@hpcupt1.HP.COM> williamo@hpcupt1.HP.COM (William O'Saughnessy) writes:
>
>OK, what is the proper and portable way to get a character from stdin
>without having it echoed to the screen?!!!!

I wonder what makes this such a misunderstood and flammable topic.

Is it such a problem to consider things such as echo, line editing
and other terminal management tasks be the domain of the operating system,
(and as such, machine-dependent) ?

Isn't ioctl(), stty(), or fcntl() [or similar device management routine] in
the same manual as getchar() [no flames about different volumes, please :-)] ?

>Basic may have C beat here it defines the way with INKEY but there 
>appears to be no machine independent way of doing it in C!

I haven't got much Basic experience, but suspect that if the Basic INKEY
function is one which solicits raw (non echoed, key-at-a-time) keyboard input,
there is one which will solicite cooked (echoed, editable, line-at-a-time)
input as well.

swilson%thetone@Sun.COM (Scott Wilson) (08/20/88)

In article <371@marob.MASA.COM> daveh@marob.masa.com (Dave Hammond) writes:
>Isn't ioctl(), stty(), or fcntl() [or similar device management routine] in
>the same manual as getchar() [no flames about different volumes, please :-)] ?

Again, the system with which I have the problem is THINK's LightspeedC on
a Macintosh.  No there isn't ioctl(), stty(), fcntl(), terminals,
terminal emulation windows, or terminal drivers.  Making a window look
like a terminal is a function of the C libraries.  And, again, the problem is
that standards like ANSI appear to leave echoing alone because it is an
OS issue.  My question is how do we get getchars that behave similarly
on different systems when for some implementations it falls under the
responsibility of the C libraries because the OS doesn't have terminal
support.

--
Scott Wilson		arpa: swilson@sun.com
Sun Microsystems	uucp: ...!sun!swilson
Mt. View, CA

mcdonald@uxe.cso.uiuc.edu (08/20/88)

>>OK, what is the proper and portable way to get a character from stdin
>>without having it echoed to the screen?!!!!

>I wonder what makes this such a misunderstood and flammable topic.

I know the answer to that one!

>Is it such a problem to consider things such as echo, line editing
>and other terminal management tasks be the domain of the operating system,
>(and as such, machine-dependent) ?

It is indeed a problem, but that's the way it is. Too bad all 
operating systems can't do it right (i.e. like MS-DOS :-) )

>Isn't ioctl(), stty(), or fcntl() [or similar device management routine] in
>the same manual as getchar() [no flames about different volumes, please :-)] ?

No, in fact a careful look at my C manuals finds no reference to them
at all. I have absolutely no idea how to use them, or their exact use.
I can guess something from the names - that is all.

egisin@watmath.waterloo.edu (Eric Gisin) (08/20/88)

In article <65071@sun.uucp>, swilson%thetone@Sun.COM (Scott Wilson) writes:
> Again, the system with which I have the problem is THINK's LightspeedC on
> a Macintosh.  No there isn't ioctl(), stty(), fcntl(), terminals,
> terminal emulation windows, or terminal drivers.  Making a window look
> like a terminal is a function of the C libraries.  And, again, the problem is
> that standards like ANSI appear to leave echoing alone because it is an
> OS issue.  My question is how do we get getchars that behave similarly
> on different systems when for some implementations it falls under the
> responsibility of the C libraries because the OS doesn't have terminal
> support.
> 

If the OS doesn't have terminal support,
the C library should support it,
and it should be the *default* for un-redirected stdout/stdin.
If the programmer wants unechoed keyboard input,
they can call non-portable OS functions.
If LightspeedC doesn't work that way,
complain to THINK, or get better compiler.

alanf%smile@Sun.COM (Alan Fargusson) (08/23/88)

I have always thought that this was an omission in the stdio I/O library.
If turning echo on and off was defined as part of fread, fwrite, printf, ...
then there would be no problem.  As it is now you kind of take your chances
with various version of UNIX, and non UNIX systems are hopeless (as far as
portability that is).

It is to late to get this into the ANSI-C standard I guess.
- - - - - - - - - - - - - - - - - - - - -
Alan Fargusson		Sun Microsystems
alanf@sun.com		..!sun!alanf

ok@quintus.uucp (Richard A. O'Keefe) (08/23/88)

In article <65197@sun.uucp> alanf%smile@Sun.COM (Alan Fargusson) writes:
>I have always thought that this was an omission in the stdio I/O library.
>If turning echo on and off was defined as part of fread, fwrite, printf, ...
>then there would be no problem.  As it is now you kind of take your chances
>with various version of UNIX, and non UNIX systems are hopeless (as far as
>portability that is).

(1) Don't forget, the C standard has to make sense on IBM mainframes,
    which do not use a character-at-a-time interface to their terminals.
(2) The dpANS makes it clear that fgets() and getchar() are supposed to
    do the same things (in general), so if one of them echoes and the
    other doesn't, that's broken.
(3) The story with respect to UNIX and MS-DOS is nowhere near as bad as
    has been made out: yes the terminal ioctl() calls differ between BSD
    and Sys V, but if you want to control features like echoing you
    should probably be using Curses, and while there are differences,
    they aren't _that_ great.  There are implementations of Curses for
    MS-DOS, and even VMS tries to support that interface.

I loathe Curses myself, but it _is_ a de facto standard, and is being
used successfully by a lot of applications programmers.  It seems to
me that the appropriate thing to do is to propose that Curses be part
of the next version of the C standard (perhaps as an optional module
so that IBM won't have to bring their operating systems into the '70s).

les@chinet.UUCP (Leslie Mikesell) (08/23/88)

In article <65197@sun.uucp> alanf%smile@Sun.COM (Alan Fargusson) writes:
>I have always thought that this was an omission in the stdio I/O library.
>If turning echo on and off was defined as part of fread, fwrite, printf, ...
>then there would be no problem.  As it is now you kind of take your chances
>with various version of UNIX, and non UNIX systems are hopeless (as far as
>portability that is).

Maybe...  What if you want to run from a half-duplex terminal?  There are
good reasons for this, like using a satellite link where there may be
a several-second delay in the echo.  If stdio provided the echo, every
application would need to know how to turn if off.  Handling it in the
OS/tty driver makes everything work automatically.  Perhaps PC types don't
consider the possibility of having the keyboard and CPU separated by many
thousands of miles.

>It is to late to get this into the ANSI-C standard I guess.

It is questionable whether it belongs there.  Perhaps there should be
a standard library interface to the OS or an emulation if the OS
doesn't provide the service.  However, if an application routinely
enables echo it will cause trouble in environments where the echo is
provided elsewhere.

Les Mikesell

gwyn@smoke.ARPA (Doug Gwyn ) (08/23/88)

In article <65197@sun.uucp> alanf%smile@Sun.COM (Alan Fargusson) writes:
>If turning echo on and off was defined as part of fread, fwrite, printf, ...
>then there would be no problem.

RONG.  Making applications control the environment they are run in would
be a massive mistake!

henry@utzoo.uucp (Henry Spencer) (08/23/88)

In article <65197@sun.uucp> alanf%smile@Sun.COM (Alan Fargusson) writes:
>I have always thought that this was an omission in the stdio I/O library.
>If turning echo on and off was defined as part of fread, fwrite, printf, ...
>
>It is to late to get this into the ANSI-C standard I guess.

Much too late.  But I believe POSIX's latest revision has included a set
of terminal-control functions that look plausible.
-- 
Intel CPUs are not defective,  |     Henry Spencer at U of Toronto Zoology
they just act that way.        | uunet!attcan!utzoo!henry henry@zoo.toronto.edu

henry@utzoo.uucp (Henry Spencer) (08/23/88)

In article <302@quintus.UUCP> ok@quintus.UUCP (Richard A. O'Keefe) writes:
>    ... if you want to control features like echoing you
>    should probably be using Curses...

Urk.  No!  Control of echoing and such is fairly nicely done in Curses,
but there is too much other baggage involved.  What you should be using, as
soon as it becomes available, is the POSIX set of terminal-control functions
(unless it's changed again, POSIX terminal control is now done by a bunch of
little functions rather than by an ioctl-style one-big-struct interface).
-- 
Intel CPUs are not defective,  |     Henry Spencer at U of Toronto Zoology
they just act that way.        | uunet!attcan!utzoo!henry henry@zoo.toronto.edu

alanf%smile@Sun.COM (Alan Fargusson) (08/24/88)

In article <302@quintus.UUCP>, ok@quintus.uucp (Richard A. O'Keefe) writes:
> (1) Don't forget, the C standard has to make sense on IBM mainframes,
>     which do not use a character-at-a-time interface to their terminals.

I didn't.  This has nothing to do with turning off echo, and you can cause the
IBM terminals to blank out the input area when echo is off so it does not
echo in effect.  BTW it is possible to do character at a time input from these
guys, but it is very inefficient.

> (2) The dpANS makes it clear that fgets() and getchar() are supposed to
>     do the same things (in general), so if one of them echoes and the
>     other doesn't, that's broken.

I completely agree.  What I think should happen is if you do a fnoecho( stdin )
then both will not echo.  I just made up fnoecho(), it could be called whatever.

> (3) The story with respect to UNIX and MS-DOS is nowhere near as bad as
>     has been made out: yes the terminal ioctl() calls differ between BSD
>     and Sys V, but if you want to control features like echoing you
>     should probably be using Curses, and while there are differences,
>     they aren't _that_ great.  There are implementations of Curses for
>     MS-DOS, and even VMS tries to support that interface.

It is bad enough.  I maintained a runtime library that had to turn echo off and
do some other things, and it was a real bear to keep it working on all the
various flavors of UNIX.  We couldn't use curses for this due to some
limitations that I can't remember now.  I think it had something to do with
supporting color terminals.

> 
> I loathe Curses myself, but it _is_ a de facto standard, and is being
> used successfully by a lot of applications programmers.  It seems to
> me that the appropriate thing to do is to propose that Curses be part
> of the next version of the C standard (perhaps as an optional module
> so that IBM won't have to bring their operating systems into the '70s).

I happen to like curses actually, but for simply turning echo off for a short
time, then turning it back on the overhead is to high.  It just isn't the right
tool for this job.
- - - - - - - - - - - - - - - - - - - - -
Alan Fargusson		Sun Microsystems
alanf@sun.com		..!sun!alanf

ok@quintus.uucp (Richard A. O'Keefe) (08/24/88)

In article <1988Aug23.164855.26679@utzoo.uucp> henry@utzoo.uucp (Henry Spencer) writes:
>In article <302@quintus.UUCP> ok@quintus.UUCP (Richard A. O'Keefe) writes:
>>    ... if you want to control features like echoing you
>>    should probably be using Curses...
>
>Urk.  No!  Control of echoing and such is fairly nicely done in Curses,
>but there is too much other baggage involved.  What you should be using, as
>soon as it becomes available, is the POSIX set of terminal-control functions
>(unless it's changed again, POSIX terminal control is now done by a bunch of
>little functions rather than by an ioctl-style one-big-struct interface).

Please explain what is wrong with my suggestion.
Who _cares_ how much baggage comes with Curses?
(a) I don't have to write it.
(b) I don't have to use the other stuff.
(c) On a paging system, I don't even have to page the other stuff in.
The basic point is that implementations of Curses exist *NOW* for
	BSD UNIX
	System V
	VMS
	MS-DOS
I don't see POSIX having much impact on MS-DOS, and surmise that VMS may
not conform to POSIX for a few years yet.  Using Curses (loathesome though
I find it) is more portable than using POSIX features that generally aren't
available yet.  (We have about half-a-dozen varieties of UNIX here, and
none of them has POSIX terminal control.)

I also meant to suggest, but did not say plainly enough, that somone who
wants control over echoing is likely to want other forms of control over
the terminal (if not now, then in the next revision of the program) which
are provided in Curses but aren't attainable by means of a few #ifdefs in
a page of code as echo control is.

swilson%thetone@Sun.COM (Scott Wilson) (08/24/88)

>Who _cares_ how much baggage comes with Curses?
>(a) I don't have to write it.
>(b) I don't have to use the other stuff.
>(c) On a paging system, I don't even have to page the other stuff in.
>The basic point is that implementations of Curses exist *NOW* for
>	BSD UNIX
>	System V
>	VMS
>	MS-DOS

I care, other people care.  Some of us are developing C programs
on machines like the Macintosh where you are trying to fit your
OS stuff, your C programming tools, and your C project onto two
800K floppies.  This is comp.lang.c, not comp.lang.c.on.a.big.machine.
with.megabytes.of.disk.space.and.maybe.paging.  Size is important.
And curses is not universally available.

--
Scott Wilson		arpa: swilson@sun.com
Sun Microsystems	uucp: ...!sun!swilson
Mt. View, CA

ok@quintus.uucp (Richard A. O'Keefe) (08/25/88)

In article <65474@sun.uucp> swilson@sun.UUCP (Scott Wilson) writes:
>>Who _cares_ how much baggage comes with Curses?
>I care, other people care.  Some of us are developing C programs
>on machines like the Macintosh where you are trying to fit your
>OS stuff, your C programming tools, and your C project onto two
>800K floppies.  This is comp.lang.c, not comp.lang.c.on.a.big.machine.
>with.megabytes.of.disk.space.and.maybe.paging.  Size is important.
>And curses is not universally available.

My word, how things have changed!  Little wee IBM PCs running MS-DOS
are now "big.machines.with.megabytes.of.disk.space.and.maybe.paging"!
(I believe that there is a version of Curses for the Atari ST, too.)
If you are working on a Macintosh, POSIX features aren't going to help
you one tiny little bit either.

What in the world is wrong with taking the bits of the Curses *interface*
that you need, specifically the functions echo() and noecho(), and using
them in your code?  Ok, in the Macintosh version of your program, you will
have to write a small Macintosh-specific file to implement them.  Do
everyone a favour:  post the sources to comp.sys.apple.mac or whatever it
is called.  That's the way to produce a de facto standard, and that's how
we'll get echo control in the next version of ANSI C.

daveh@marob.MASA.COM (Dave Hammond) (08/26/88)

In article <65474@sun.uucp> swilson@sun.UUCP (Scott Wilson) writes:
>..............  This is comp.lang.c, not comp.lang.c.on.a.big.machine.
                                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>with.megabytes.of.disk.space.and.maybe.paging.  Size is important.
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 I love it !

Dave

karl@haddock.ima.isc.com (Karl Heuer) (08/26/88)

In article <65474@sun.uucp> swilson%thetone@Sun.COM (Scott Wilson) writes:
>[ok@quintus (Richard O'Keefe) writes:]
>>Who _cares_ how much baggage comes with Curses?
>
>[On a small machine, it makes a difference.]
>And curses is not universally available.

And if all I want is to read a raw character (no echo and no line editing),
then curses is not only overkill, but may not work.  What if I don't have a
termcap/terminfo entry?  The ioctl doesn't need it, but at least one version
of curses will silently exit(1) if it can't find one.  Also, I believe that
curses insists on having complete control over the terminal; you can't
reliably use stdio while curses is active.  Finally, endwin() always attempts
to move the cursor to the bottom of the screen, which is inappropriate.

(A background voice is heard: "Why don't you suggest something better, then?")

See my next article.

Karl W. Z. Heuer (ima!haddock!karl or karl@haddock.isc.com), The Walking Lint

karl@haddock.ima.isc.com (Karl Heuer) (08/26/88)

Okay, we know that ANSI didn't standardize a raw-character input function.
Some have expressed the opinion that they couldn't, because such functionality
is not univerally available.  I disagree: they could easily specify that the
function is allowed to return a failure code.  (Note that the time() function
must exist on all ANSI implementations, but is permitted to return (time_t)-1
if there isn't a system clock.)  Let's try to design an appropriate interface.

Let's begin by ignoring the issue of exactly what "raw" means, and whether it
applies to the real terminal despite redirection, or to stdin or a stream of
the user's choice.  We can argue that out later.  We need a minimum of three
functions, which I'll call rawenable(), rawdisable(), getrawchar().

The system is always in one of two states, cooked or raw, with the initial
state being cooked.  (This does not imply that echoing occurs or that line
editing is possible; it's simply a name for the initial state.)  rawenable()
and rawdisable() change the state from cooked to raw or from raw to cooked,
respectively; if called from the "wrong" state, the behavior is undefined.  If
the implementation is unable to honor the request (because there is no OS
support for raw input, or because there is no terminal attached), the function
returns -1; otherwise it returns 0.

If getrawchar() is called from cooked mode, or any stdio function from raw
mode, the behavior is undefined.  When there are unread characters in the
stdin stream (as a result of ungetc() or OS-level line buffering), it is
implementation-defined whether getrawchar() behaves like getchar() or acts
independently of stdio.

In practice, some implementations will make rawenable() and rawdisable()
no-ops, and getrawchar() a system call; others will put the system calls into
rawenable() and rawdisable(), and make getrawchar() a synonym for getchar().
The model is designed to allow efficient implementation on a wide variety of
architectures.

This is a first cut at a solution; it can probably be improved.  Comments?

Karl W. Z. Heuer (ima!haddock!karl or karl@haddock.isc.com), The Walking Lint

dhesi@bsu-cs.UUCP (Rahul Dhesi) (08/26/88)

In article <6589@haddock.ima.isc.com> karl@haddock.isc.com (Karl Heuer) writes:
>The system is always in one of two states, cooked or raw, with the initial
>state being cooked.

It would be nice if we applied the concept of raw-versus-cooked to the
current input request rather than to the terminal.  This way there is
no danger of programming carelessness (or having to kill a runaway
process) leaving the terminal in a funny state.  This happens more
often than I like on UNIX systems.
-- 
Rahul Dhesi         UUCP:  <backbones>!{iuvax,pur-ee,uunet}!bsu-cs!dhesi

ok@quintus.uucp (Richard A. O'Keefe) (08/26/88)

In article <6589@haddock.ima.isc.com> karl@haddock.isc.com (Karl Heuer)
proposes a
	rawenable(), getrawchar(), rawdisable()
interface.

>Let's begin by ignoring the issue of exactly what "raw" means.

Let's not.  The original topic was reading without _echoing_, which is
not the same thing as reading without line-editing.  For example, when
entering a password, I do *not* want it echoed (not even as "#"s, which
is what login does on our Sun 386i, naughty naughty) but I *do* want to
be able to correct it as I enter it.  Then there's the question of what
interrupt characters are heeded (which should be done per-character, but
that's another story).  Then again, there's the distinction between
function keys sending escape sequence -vs- "keycodes".  If I expect to
read function keys as raw codes of some sort, how do I do that so that
it will work on IBM PCs and Apollos?  (Curses *does* map function keys
to keycodes for you...)

A program which is connected to a "terminal" might be connected directly
to a keyboard, or it might be connected through a network.  "raw" might
well mean different things in those two cases.  When you are using STREAMS,
which modules are absent when you're in raw mode?

>If getrawchar() is called from cooked mode, or any stdio function from raw
>mode, the behavior is undefined.

Does this mean ANY sort of stdio, or only stdio to streams which are not
known not to be terminals?  Why shouldn't I be allowed to write to a disc
file while the terminal is in raw mode?

steve@umigw.MIAMI.EDU (steve emmerson) (08/26/88)

In article <6589@haddock.ima.isc.com> karl@haddock.isc.com (Karl Heuer) writes:
>Rawenable() and rawdisable() change the state from cooked to raw or 
>from raw to cooked, respectively; if called from the "wrong" state, 
>the behavior is undefined.

I would prefer that rawenable() and rawdisable() be idempotent* rather 
than undefined, unless, of course, this means that they can't be 
implemented on some systems.

I believe this would enable slightly cleaner programs as the relevant
state information would be contained (at least conceptually) in the
raw{en,dis}able()/getrawchar() module -- discharging the programer from
responsibility over the matter.

------------
* "idempotent" means that the effect of calling it twice is the same as 
calling it once, i.e. the second call is a functional no-op.)
-- 
Steve Emmerson                     Inet: steve@umigw.miami.edu [128.116.10.1]
SPAN: miami::emmerson (host 3074::)      emmerson%miami.span@star.stanford.edu
UUCP: ...!ncar!umigw!steve               emmerson%miami.span@vlsi.jpl.nasa.gov
"Computers are like God in the Old Testament: lots of rules and no mercy"

bill@proxftl.UUCP (T. William Wells) (08/26/88)

In article <65071@sun.uucp> swilson@sun.UUCP (Scott Wilson) writes:
:                                                   Making a window look
: like a terminal is a function of the C libraries.

Agreed.  And your compiler is broken for not doing this
correctly.  I know that doesn't help you but I can suggest a
kludge:

If you use getchar() exclusively, you might be able to avoid the
problem by modifying stdio.h.  You see, getchar is often
implemented as a macro:

#define getchar()       getc(stdin)

or some such.  You could edit your stdio.h so that the macro is
something like:

#define getchar()       (putchar(getchar()))

This has the advantage of leaving your program portable but the
disadvantage of using a non-standard configuration for your
compiler (watch those upgrades!).  And, if you slip and use
something else, you'll get surprised.

:            My question is how do we get getchars that behave similarly
: on different systems when for some implementations it falls under the
: responsibility of the C libraries because the OS doesn't have terminal
: support.

The way you get such getchars is to buy the compiler that
provides them.  I'm serious.  You got screwed by this compiler
implementer (I'll take that back if they fix this bug).
Standards will *not* fix the problem if the implementers do not
adhere to them.

As for interactive terminals, I do not know of *any* other system
that does not provide echoing under normal circumstances when one
does getchar().  (No doubt that will provoke a flood of
counterexamples.  So be it.) Your apparent lack of uniformity
appears to be an artifact of a compiler that fails to conform to
the de facto standards.  You certainly can't complain if it fails
to conform to the ANSI standard, as that *does not* exist.  Yet.

It does appear to be the case that the *proposed* ANSI standard
is somewhat, shall we say, concise :-) when defining interactive
devices.  Here are the relevant passages.

Rationale 2.1.2.3:

"The class of *interactive devices* is intended to include at
least asynchronous terminals, or paired display screens and
keyboards.  An implementation may extend the definition to
include other input and output devices or even network
inter-program connections, provided they obey the Standard's
characterization of interactivity."

2.1.2.3:

"The input and output dynamics of interactive devices shall take
place as specified in 4.9.3.  The intent of these requirements is
that unbuffered or line-buffered output appear as soon as
possible, to ensure that prompting messages actually appear prior
to a program waiting for input.

What constitutes an interactive device is
implementation-defined."

4.9.3:

"...  are fully buffered if and only if the stream can be
determined not to refer to an interactive device."

4.9.5.3:

"...  is fully buffered if and only if the stream can be
determined not to refer to an interactive device."

And that, I am afraid, would seem to be all.

To clarify this for those on comp.std.c (to which this has been
cross-posted), the original complaint was that his compiler's
getchar() does not echo characters!  I agree with him that an
interactive device ought to be defined as one intended to provide
echoing of some kind of the user's input.

The third draft does not seem to say anything like this.  Does
anyone out there have any additional information?  If not, I'll
ask that they add this to the standard.  It ought to be
acceptable, as this would seem to be an editorial change -- is it
interactive if you can't see your input??!


---
Bill
novavax!proxftl!bill

bill@proxftl.UUCP (T. William Wells) (08/26/88)

In article <65197@sun.uucp> alanf%smile@Sun.COM (Alan Fargusson) writes:
: I have always thought that this was an omission in the stdio I/O library.
: If turning echo on and off was defined as part of fread, fwrite, printf, ...
: then there would be no problem.  As it is now you kind of take your chances
: with various version of UNIX, and non UNIX systems are hopeless (as far as
: portability that is).

It is remotely possible that requiring echoing could be put into
the standard as an "editorial change".  There is not a chance in
hell that control of echoing will.  I seriously doubt that it
ever will, as there are important systems where turning off
echoing is *not* possible since echoing is done by parts of the
hardware that can't be affected by the system.

---
Bill
novavax!proxftl!bill

karl@haddock.ima.isc.com (Karl Heuer) (08/26/88)

In article <3761@bsu-cs.UUCP> dhesi@bsu-cs.UUCP (Rahul Dhesi) writes:
>In article <6589@haddock.ima.isc.com> karl@haddock (Karl Heuer) writes:
>>The system is always in one of two states, cooked or raw
>
>It would be nice if we applied the concept of raw-versus-cooked to the
>current input request rather than to the terminal.  This way there is
>no danger of programming carelessness (or having to kill a runaway
>process) leaving the terminal in a funny state.  This happens more
>often than I like on UNIX systems.

While this behavior may be more desirable for some applications, insisting on
it would require too much overhead on UNIX.  My proposal was designed so that
	rawenable();
	while ((c = getrawchar()) != QUIT_CMD) do_command(c);
	rawdisable();
could be implemented with just one system call (instead of three) for each
iteration of the loop.

To defend against the "funny state" problem, you can set up traps:
	signal(SIGINT, rawdisable);
	atexit(rawdisable);
(My "tio" package has an option to automatically do this when you call the
equivalent of rawenable().)

Alternately, you could get the exact behavior you described by wrapping
another layer around the primitives:
	int getch(void) {
		int c;
		rawenable(); c = getrawchar(); rawdisable();
		return c;
	}

If what you're really saying is that UNIX should be changed, then I agree (a
"/dev/rtty" would be within the Spirit).  But that's not a C issue.

Karl W. Z. Heuer (ima!haddock!karl or karl@haddock.isc.com), The Walking Lint

henry@utzoo.uucp (Henry Spencer) (08/27/88)

In article <313@quintus.UUCP> ok@quintus.UUCP (Richard A. O'Keefe) writes:
>... post the sources to comp.sys.apple.mac or whatever it
>is called.  That's the way to produce a de facto standard, and that's how
>we'll get echo control in the next version of ANSI C.

If you propose this, the odds are very high that X3J11 will say "(a) this
is not a portable construct, since some operating systems cannot implement
it; (b) POSIX already does this" and reject it.

Admittedly, POSIX is not here yet... but *that's* the standardized interface
for such things that you should be trying to use.  I would expect to see
subsets of that interface made available in most non-Unix C implementations
as well.
-- 
Intel CPUs are not defective,  |     Henry Spencer at U of Toronto Zoology
they just act that way.        | uunet!attcan!utzoo!henry henry@zoo.toronto.edu

gwyn@smoke.ARPA (Doug Gwyn ) (08/27/88)

In article <624@proxftl.UUCP> bill@proxftl.UUCP (T. William Wells) writes:
>#define getchar()       (putchar(getchar()))

Ahem.  Consider (in UNIX shell notation):
	filter <infile >outfile

There really is no way to do this right in the application code;
it has to be dealt with in the run-time environment.

gwyn@smoke.ARPA (Doug Gwyn ) (08/28/88)

In article <1988Aug26.170448.23115@utzoo.uucp> henry@utzoo.uucp (Henry Spencer) writes:
>Admittedly, POSIX is not here yet...

Actually, it is, at least the part (1003.1) you're talking about.
A couple of days ago I got a note from Jim Isaak saying that the
final IEEE Std 1003.1 had been approved.  (Draft 13, I think.)

bill@proxftl.UUCP (T. William Wells) (08/29/88)

In article <8384@smoke.ARPA> gwyn@brl.arpa (Doug Gwyn (VLD/VMB) <gwyn>) writes:
: In article <624@proxftl.UUCP> bill@proxftl.UUCP (T. William Wells) writes:
: >#define getchar()       (putchar(getchar()))
:
: Ahem.  Consider (in UNIX shell notation):
:       filter <infile >outfile
:
: There really is no way to do this right in the application code;
: it has to be dealt with in the run-time environment.

Please recall that he wanted a fix for his Macintosh, where there
is no such thing as a command line, much less redirection.
(Actually, I hear that there is a kludge in Lightspeed C that
lets the user type in part of a command line at program start;
but according to a guy who is working with that compiler,
getchar() echoes when this kludge is used, so I suppose that the
guy with the problem isn't using this kludge.)

Of course, you really should have got me for this; I wrote:

: #define getchar()       (putchar(getchar()))

And I should have written:

: #define getchar()       (putchar(getc(stdin)))

I do agree that this would be a brain-damaged thing to do on
almost any other system.  And, I agree, the run-time environment
should deal with this; that was the first thing I said in the
message that you responded to:

In article <624@proxftl.UUCP> I wrote:
: In article <65071@sun.uucp> swilson@sun.UUCP (Scott Wilson) writes:
: :                                                   Making a window look
: : like a terminal is a function of the C libraries.
:
: Agreed.  And your compiler is broken for not doing this
: correctly.

---
Bill
novavax!proxftl!bill

peter@ficc.uu.net (Peter da Silva) (08/29/88)

In article <627@proxftl.UUCP>, bill@proxftl.UUCP (T. William Wells) writes:
> ever will, as there are important systems where turning off
> echoing is *not* possible since echoing is done by parts of the
> hardware that can't be affected by the system.

I haven't used IBM systems, but the batch terminal systems I'm familiar
with at least allow you to change the characters to black-on-black, which
is adequate for a password...
-- 
Peter da Silva  `-_-'  Ferranti International Controls Corporation.
"Have you hugged  U  your wolf today?"            peter@ficc.uu.net

mercer@ncrcce.StPaul.NCR.COM (Dan Mercer) (08/30/88)

	Another one of those fine confused wish list discussions.  Unfortunately,
	like the other discussions of this type,  it is fatally flawed.	
	The problem is,   evreyone seems to be confusing language functionality
	with os functionality.  Terminal echo is a function provided by the
	operating system (in this case,  UNIX(tm)).  Whether or not echoing
	is going on is invisible to getchar(),  and read.  The tty device driver
	is controlling this operation,  and only an ioctl can change its
	behaviour.  In many cases,  the echoing function is not even taking
	place on the same processor.  In the NCR TOWER(tm) series,  the
	echoing is being done on the HPSIO (a separate 68010 based processor)
	and is thereby not burdening the CPU. 

	In Amdahl hosts running UTS in a network,  the echoing may be
	done by and Amdahl 4705(tm) channel attached to the host.
	Ioctl calls will generate commnds to the front end processor to
	change its character reading behaviour.

	In fact,  in many cases,  the echo may already have occurred
	before the echoing can be turned off.

	Before you go mucking with the language,  I suggest you learn
	a bit more about your hardware,  your operating system,  and
	how they interrelate.  Then I suggest you do what I did when I
	wrote a menuing system - read everything available about the
	tty device drivers,  stty,  and termio,  experiment like
	crazy,  then write your own raw character input routines.

	No flame intended.

	Dan Mercer - NCR COMTEN

ok@quintus.uucp (Richard A. O'Keefe) (08/30/88)

In article <1988Aug26.170448.23115@utzoo.uucp> henry@utzoo.uucp (Henry Spencer) writes:
>In article <313@quintus.UUCP> ok@quintus.UUCP (Richard A. O'Keefe) writes:
>>[about echo control]
>Admittedly, POSIX is not here yet... but *that's* the standardized interface
>for such things that you should be trying to use.  I would expect to see
>subsets of that interface made available in most non-Unix C implementations
>as well.

Given that the main criticism of my proposal to use the Curses interface
was that Curses carries too much with it, I imagine that this won't please
*present* Macintosh users (other than A/UX users) much either.  I'd be
delighted to use POSIX terminal control, except that we don't seem to have
it on our Suns yet, or any of our other machines either.

(1) Is the POSIX terminal interface settled yet?
(2) Which vendors have hinted at a shipping date for POSIX-compatible
    terminal control? (serious)  Have the OSF? (joke)
(3) Has anyone produced a free "approximation" of the POSIX terminal
    interface which can sit on top of either BSD 4.3 or V.3?

swilson%thetone@Sun.COM (Scott Wilson) (08/31/88)

In article <731@ncrcce.StPaul.NCR.COM> mercer@ncrcce.StPaul.NCR.COM (Dan Mercer) writes:
>Terminal echo is a function provided by the
>operating system (in this case,  UNIX(tm)).

Who said we were talking about UNIX?  Again, for the nth time, the environment
in question is THINK's Lightspeed C 3.0 running on a Macintosh under MacOS.
There are no terminals, terminal drivers, terminal emulation windows, stty,
or ioctl's.  Any terminal emulation is provided by the C runtime libraries.

Under UNIX, echoing clearly falls under the realm of the operating system
and it would be wrong for a language to specify something that it can't
or shouldn't control.  I think the real question is that in abscence of OS
support for terminals (or interactive input) should the C environment be
forced to provide a "normal" input mechanism including echoing and maybe
primitive line editing.

--
Scott Wilson		arpa: swilson@sun.com
Sun Microsystems	uucp: ...!sun!swilson
Mt. View, CA

terry@wsccs.UUCP (Every system needs one) (08/31/88)

In article <313@quintus.UUCP>, ok@quintus.uucp (Richard A. O'Keefe) writes:
> In article <65474@sun.uucp> swilson@sun.UUCP (Scott Wilson) writes:
> >>Who _cares_ how much baggage comes with Curses?
> >I care, other people care.  Some of us are developing C programs
> >on machines like the Macintosh where you are trying to fit your
> >OS stuff, your C programming tools, and your C project onto two
> >800K floppies.  This is comp.lang.c, not comp.lang.c.on.a.big.machine.
> >with.megabytes.of.disk.space.and.maybe.paging.  Size is important.
> >And curses is not universally available.

Bravo, Scott!

> My word, how things have changed!  Little wee IBM PCs running MS-DOS
> are now "big.machines.with.megabytes.of.disk.space.and.maybe.paging"!
> (I believe that there is a version of Curses for the Atari ST, too.)
> If you are working on a Macintosh, POSIX features aren't going to help
> you one tiny little bit either.

No, we're talking curses, not something else.  Does AT&T say this package
of which you speak is curses?

> What in the world is wrong with taking the bits of the Curses *interface*
> that you need, specifically the functions echo() and noecho(), and using
> them in your code?  Ok, in the Macintosh version of your program, you will
> have to write a small Macintosh-specific file to implement them.  Do
> everyone a favour:  post the sources to comp.sys.apple.mac or whatever it
> is called.  That's the way to produce a de facto standard, and that's how
> we'll get echo control in the next version of ANSI C.

<FFFFFFLLLLLAAAAAMMMMMEEEEE GHHHHHOOOOSSSSSSST! (like 'Space Ghost')>

Urk.  "what's wrong?"?  Try Copyright AT&T.

Besides, curses is seriously buggy in a number of places, like:

	XS,XN,AM,SG,UG,GG,tputs(), etc.

I can site specific examples; the one you are probably curious about, is,
however, tputs().

	1) It doesn't necessarily cause an I/O to occur in a single write
	   operation.  This is BAD as transparent printing gets more
	   popular, and seriously kills paged-screen multiple sessions.

	2) Not all implementations know about pad characters, and instead
	   print the numbers on the screen.

The tgetent() does not malloc() the save area; you have to know how big
the maximum area is going to be beforehand when you're coding your own
code; that's bad enough... but if some idiot has a monster termcap/info
entry, curses can't be made happy without kludges.

Curses depends (according to SVID) on the terminfo file.  This is a kludge.

	1) It is not extensible.  It depends on a struct compiled into
	   libcurses.

	2) It is hard to fix.  Most manufacturers do not provide source.

	3) Many terminal definitions are wrong; specifically, SCO Xenix
	   is the only system I've seen that has gotten the Wyse-50 and
	   the Televideo 950 graphics correct, and I had a lot to do with
	   that.  True, it's usually broken in termcap, but at least I
	   can fix that.

	4) It will not work with a true VT100 terminal or emualation.
	   Since VT100's are probably the most emulated terminal, this
	   is stupid, and obviously a result of poor or no testing.  I
	   expect a company like AT&T to be able to afford one of each
	   of the terminals they say they support, considering what they
	   are charging for a liscence.  To get it to work, you have to
	   lie and say you are on a 'vt100-nam' or remove the "AM" attr.

Standout is not properly handled.  In most cases, there is a "protect"
bit which can be used in lieu of reverse to at least correctly emulate
standout.  This is true of all Wyse and Televideo terminals.

Curses is brain-damaged with windows.  The window implementation is
bad in that it

	1) Does not understand hardware scrolling (though this is more
	   a terminfo fault, in that it can not be extended to fix
	   this deficiency anyway).

	2) Can not move a window in the background while leaving another
	   in the foreground untouched.  This is the fault of the model
	   used to implement the window and it's memory mapping.  Layered
	   windows were chosen to avoid "excessive memory allocation" for
	   the save buffer area.  The point of diminishing returns, to
	   correct this misinformation, is when all windows are n x m or
	   larger where n+1 x m+1 is the virtual screen size.

There are no field input primitives.

Typical code sizes change from:

	270k -> 288k
	508k -> 527k

when libcurses  is used instead of libtermcap.  While it is true that
disk space is no longer a problem on most systems, space on distribution
media is limited.  This is an 18-19k increase, and can force an additional
disk if there are several executables and distribution space is already
tight (it has in 3 cases at our company, due to the target system no
longer supporting termcap).


Internationalization is hard when most implementations use the 8th bit
for their own nefariousness (using a short yields 9 attr bits that way).

It is ridiculous to think that a company would ship a product *HEAVILY*
dependant on it's display without writing their own code or buying
someone elses.

Need I say more?

<Unflame without much enthusiasm>

| Terry Lambert           UUCP: ...{ decvax, ihnp4 } ...utah-cs!century!terry |
| @ Century Software        OR: ...utah-cs!uplherc!sp7040!obie!wsccs!terry    |
| SLC, Utah                                                                   |
|                   These opinions are not my companies, but if you find them |
|                   useful, send a $20.00 donation to Brisbane Australia...   |
|                   'I have an eight user poetic liscence' - me               |

mcdonald@uxe.cso.uiuc.edu (08/31/88)

	>Another one of those fine confused wish list discussions.  Unfortunately,
	>like the other discussions of this type,  it is fatally flawed.	
	>The problem is,   evreyone seems to be confusing language functionality
	>with os functionality.  Terminal echo is a function provided by the
	>operating system (in this case,  UNIX(tm)).  Whether or not echoing
	>is going on is invisible to getchar(),  and read.  The tty device driver
	>is controlling this operation,  and only an ioctl can change its
	>behaviour.  In many cases,  the echoing function is not even taking
	>place on the same processor.  In the NCR TOWER(tm) series,  the
	>echoing is being done on the HPSIO (a separate 68010 based processor)
	>and is thereby not burdening the CPU. 


>	Before you go mucking with the language,  I suggest you learn
>	a bit more about your hardware,  your operating system,  and
>	how they interrelate.  Then I suggest you do what I did when I
>	wrote a menuing system - read everything available about the
>	tty device drivers,  stty,  and termio,  experiment like
>	crazy,  then write your own raw character input routines.

We want it put in the language so that programs will run portably,
and MOST IMPORTANTLY, so that operating system designers will
have to fix their operating systems so that it can be done 
portably!!!!!!!!!!

Doug McDonald

mouse@mcgill-vision.UUCP (der Mouse) (09/01/88)

In article <6589@haddock.ima.isc.com>, karl@haddock.ima.isc.com (Karl Heuer) writes:
> [raw-character input: first-cut proposal]

> rawenable() and rawdisable() change the state from cooked to raw or
> from raw to cooked, respectively; if called from the "wrong" state,
> the behavior is undefined.

I would much prefer for calling rawenable from raw mode, or rawdisable
from cooked mode, to be a no-op.  I'd also want an inquiry function, to
determine the current state.  If these features aren't provided, you
can be sure lots (most?) of the applications using this will
immediately provide

static int inrawmode = 0;
startraw(){if(!inrawmode){rawenable();inrawmode=1;}}
stopraw(){if(inrawmode){rawdisable();inrawmode=0;}}
raw_p(){return(inrawmode);}

so you might as well standardize them that way.

> If getrawchar() is called from cooked mode, or any stdio function
> from raw mode, the behavior is undefined.

Does this include all stdio functions, all stdio functions that
actually perform I/O, or only stdio functions acting on stdin (or the
stream in question, if any stream may be put in raw mode)?

> Karl W. Z. Heuer (ima!haddock!karl or karl@haddock.isc.com), The Walking Lint

					der Mouse

			old: mcgill-vision!mouse
			new: mouse@larry.mcrcim.mcgill.edu

mercer@ncrcce.StPaul.NCR.COM (Dan Mercer) (09/02/88)

In article <225800061@uxe.cso.uiuc.edu> mcdonald@uxe.cso.uiuc.edu writes:
:
:>	Before you go mucking with the language,  I suggest you learn
:>	a bit more about your hardware,  your operating system,  and
:>	how they interrelate.  Then I suggest you do what I did when I
:>	wrote a menuing system - read everything available about the
:>	tty device drivers,  stty,  and termio,  experiment like
:>	crazy,  then write your own raw character input routines.
:
:We want it put in the language so that programs will run portably,
:and MOST IMPORTANTLY, so that operating system designers will
:have to fix their operating systems so that it can be done 
:portably!!!!!!!!!!
:
:Doug McDonald

	I think you misunderstand portability.  'C' is portable because
	its not machine dependent.  The run time support libraries
	are machine dependent.  Strcpy on some systems is written in
	'C',  but in most cases,  is probably written in assembler
	to maximize machine efficiencies.

	'C' run time support differs from machine to machine,  and
	operating system to operating system.  Forking on UNIX(tm)
	creates another concurrently running process.  No such luck
	on MS-DOS(tm).

	Portability doesn't mean I can write a program for my PC and
	recompile it for my NCR Tower and expect it to run the same.
	Get real.  And don't expect operating system designers to
	redesign their operating systems just because someone's too
	dumb to figure out how to turn off echoing.


	Dan Mercer
	NCR Comten

karl@haddock.ima.isc.com (Karl Heuer) (09/03/88)

In article <319@quintus.UUCP> ok@quintus.uucp (Richard A. O'Keefe) writes:
>In article <6589@haddock.ima.isc.com> karl@haddock.isc.com (Karl Heuer)
>proposes a   rawenable(), getrawchar(), rawdisable()   interface.
>
>>Let's begin by ignoring the issue of exactly what "raw" means.
>
>Let's not.  The original topic was reading without _echoing_, which is
>not the same thing as reading without line-editing.

Right.  Which is why I didn't define "raw"; I wanted to leave open the
possibility that it could mean "with line editing, but no echo".  Such
variants can be (and are, in my current implementation) handled via arguments
passed to rawenable().  The set of legal feature-combinations is, of course,
implementation-defined.  (It may even be empty, in which case the request
always fails.)

>>If getrawchar() is called from cooked mode, or any stdio function from raw
>>mode, the behavior is undefined.
>
>Does this mean ANY sort of stdio ...?

Good point.  Let's make it "any stdio function which applies to the raw
terminal", or something like that.

In <155@umigw.MIAMI.EDU> and <1276@mcgill-vision.UUCP>, steve and mouse
suggest that rawenable() and rawdisable() should be idempotent instead of
causing undefined behavior on repetition.

But it may be better to allow them to stack, instead.  (E.g. if you want to
call getpass() from within raw mode, and if getpass() is implemented using
rawenable().)  I figured it's better to leave it undefined until the details
are worked out.

Karl W. Z. Heuer (ima!haddock!karl or karl@haddock.isc.com), The Walking Lint

tanner@cdis-1.uucp (Dr. T. Andrews) (09/05/88)

In article <733@ncrcce.StPaul.NCR.COM>, mercer@ncrcce.StPaul.NCR.COM (Dan Mercer) writes:
> Portability doesn't mean I can write a program for my PC and
> recompile it for my NCR Tower and expect it to run the same.

I would beg to differ.  What portability means to us (who supply
software for more than one machine) is exactly that: I can take a
program written for a PC, re-compile it for the NCR Tower, and
expect it to run the same.

We actually go the other direction: write on big computer, build
version for PC after it works on big computer.  We then sell both
versions.  Other than the installation and back-up instructions,
we ship the same manual, too.
-- 
...!bikini.cis.ufl.edu!ki4pv!cdis-1!tanner  ...!bpa!cdin-1!cdis-1!tanner
or...  {allegra killer gatech!uflorida decvax!ucf-cs}!ki4pv!cdis-1!tanner

mercer@ncrcce.StPaul.NCR.COM (Dan Mercer) (09/08/88)

:In article <733@ncrcce.StPaul.NCR.COM>, mercer@ncrcce.StPaul.NCR.COM (Dan Mercer) writes:
:> Portability doesn't mean I can write a program for my PC and
:> recompile it for my NCR Tower and expect it to run the same.
:
:I would beg to differ.  What portability means to us (who supply
:software for more than one machine) is exactly that: I can take a
:program written for a PC, re-compile it for the NCR Tower, and
:expect it to run the same.
:
:We actually go the other direction: write on big computer, build
:version for PC after it works on big computer.  We then sell both
:versions.  Other than the installation and back-up instructions,
:we ship the same manual, too.
:-- 
:...!bikini.cis.ufl.edu!ki4pv!cdis-1!tanner  ...!bpa!cdin-1!cdis-1!tanner
:or...  {allegra killer gatech!uflorida decvax!ucf-cs}!ki4pv!cdis-1!tanner

	One clarification on your claim - are you using the same
	operating system (UNIX(tm) - XENIX(tm)) throughout.  I
	should have clarified my statement by saying 'written
	for a PC running MS-DOS(tm), recompile it for the NCR Tower
	running UNIX(tm).'  Portability is somewhat guaranteed
	throughout the UNIX(tm) world,  that's its charm.  I
	say somewhat,  because it is possible to write non-portable
	'C' code (assuming byte sizes for pointers,  for instance,
	and not using casting when its called for).

	It is possible to write code that will port between MS-DOS(tm)
	and UNIX(tm),  but only by importing portability functions,
	like termcap and terminfo.

	To expect portability across different hardware and operating
	system architectures,  however,  just because you write in
	'C',  stretches the meaning of portability.  One shouldn't
	expect the programming language to usurp the role of an 
	operating system,  or expect the interface of the language
	to the operating system to be the same in all instances.

	And thats my objection to getchar w/wout echo.

	Dan Mercer
	NCR Comten

karl@haddock.ima.isc.com (Karl Heuer) (09/09/88)

mercer@ncrcce.StPaul.NCR.COM (Dan Mercer) writes:
>To expect portability across different hardware and operating system
>architectures, however, just because you write in 'C', stretches the meaning
>of portability.  One shouldn't expect the programming language to usurp the
>role of an operating system, or expect the interface of the language to the
>operating system to be the same in all instances.

Why not?  That's exactly what stdio does, for example.  And several other
system functions (rename(), remove()) are now part of the standard library
which must be provided with every ANSI C implementation.

On the other hand, fork() is not and should not be part of ANSI C.  So I think
the real question is whether it's *possible* to standardize a reasonable form
of raw I/O interface.  If so, I don't see any obvious reason not to do it.

Karl W. Z. Heuer (ima!haddock!karl or karl@haddock.isc.com), The Walking Lint

tanner@cdis-1.uucp (Dr. T. Andrews) (09/09/88)

In article <739@ncrcce.StPaul.NCR.COM>, mercer@ncrcce.StPaul.NCR.COM (Dan Mercer) writes:
) One clarification on your claim - are you using the same
) operating system (UNIX(tm) - XENIX(tm)) throughout.

No, we are not using the same operating system throughout.  We are
using ms-dos (or equiv) on the "PC" machine, and unix/xenix on the
bigger machines.
-- 
...!bikini.cis.ufl.edu!ki4pv!cdis-1!tanner  ...!bpa!cdin-1!cdis-1!tanner
or...  {allegra killer gatech!uflorida decvax!ucf-cs}!ki4pv!cdis-1!tanner

mercer@ncrcce.StPaul.NCR.COM (Dan Mercer) (09/13/88)

In article <7196@haddock.ima.isc.com: karl@haddock.ima.isc.com (Karl Heuer) writes:
:mercer@ncrcce.StPaul.NCR.COM (Dan Mercer) writes:
::To expect portability across different hardware and operating system
::architectures, however, just because you write in 'C', stretches the meaning
::of portability.  One shouldn't expect the programming language to usurp the
::role of an operating system, or expect the interface of the language to the
::operating system to be the same in all instances.
:
:Why not?  That's exactly what stdio does, for example.  And several other
:system functions (rename(), remove()) are now part of the standard library
:which must be provided with every ANSI C implementation.
:
:On the other hand, fork() is not and should not be part of ANSI C.  So I think
:the real question is whether it's *possible* to standardize a reasonable form
:of raw I/O interface.  If so, I don't see any obvious reason not to do it.
:
:Karl W. Z. Heuer (ima!haddock!karl or karl@haddock.isc.com), The Walking Lint

	Why not? Why not!!  Because character echo is a function of the
	output device,  not part of the character stream,  and the
	output device is part of the operating system,  not the 
	language.  Stdio's job is to format, input and output the 
	character stream,  not to control the device.

	Controlling echo is meaningless to non display input
	devices (like hard disks).  To mutilate stdio to know the
	type of input device it is getting the stream from is
	a violation.  And in systems with distributed processing
	(like NCR Towers,  where ioctl takes place in the HPSIO
	processor,  or LAN's,  where the ioctl may be distributed
	to the work stations) it isn't practical (what are you
	going to do,  send out change ioctl commands with every
	character input).

	Why don't you just find out how on your machine you turn off
	echo and roll your own programs to do stdio.  For your
	programs to be portable across different hardware schemes,
	and different operating systems,  you'll just have to do
	what the rest of us do - write code to port them.

	Dan Mercer
	NCR Comten

karl@haddock.ima.isc.com (Karl Heuer) (09/14/88)

mercer@ncrcce.StPaul.NCR.COM (Dan Mercer) writes:
>karl@haddock.ima.isc.com (Karl Heuer) writes:
>>mercer@ncrcce.StPaul.NCR.COM (Dan Mercer) writes:
>>>One shouldn't ... expect the interface of the language to the operating
>>>system to be the same in all instances.
>>
>>Why not?  That's exactly what stdio does, for example.
>
>To mutilate stdio to know the type of input device it is getting the stream
>from is a violation.

On some implementations, where completely different system calls control the
terminal and the disk, stdio already needs to know this.  (Even on UNIX, it
uses isatty() to decide which buffering scheme to use.)

>And in systems with distributed processing ... it isn't practical (what are
>you going to do, send out change ioctl commands with every character input).

If that's the only way to achieve the effect, then yes, that's what the
package has to do.  (Isn't that what the user would have to do, if he chooses
to roll his own?)  If there's a more efficient way, but it doesn't jive with
the model I proposed (rawenable(), getrawchar(), rawdisable()), then I'd like
to change the model to accommodate.  That's why I brought it up.

>Why don't you just find out how on your machine you turn off echo and roll
>your own programs to do stdio.  For your programs to be portable across
>different hardware schemes, and different operating systems, you'll just have
>to do what the rest of us do - write code to port them.

That's what I'm doing.  On various implementations, I'm finding out how to
turn off echo, and I'm encapsulating that information in a package.  I port
that package to different implementations, and any of my programs that need
the feature access it through this package.

So what do I end up with?  An interface of the language to the operating
system which is the same in all instances.

Karl W. Z. Heuer (ima!haddock!karl or karl@haddock.isc.com), The Walking Lint

ok@quintus.uucp (Richard A. O'Keefe) (09/15/88)

In article <628@wsccs.UUCP> terry@wsccs.UUCP (Every system needs one) writes:
>In article <313@quintus.UUCP>, ok@quintus.uucp (Richard A. O'Keefe) writes:
[about Curses]
>No, we're talking curses, not something else.  Does AT&T say this package
>of which you speak is curses?

My understanding is that at least one of the Curses implementations
available for the PC is based on source code released into the public
domain by AT&T.

  But may I make a really rather elementary point?

	* "Curses" is anything which provides the "Curses" interface
	
><FFFFFFLLLLLAAAAAMMMMMEEEEE GHHHHHOOOOSSSSSSST! (like 'Space Ghost')>
>
>Urk.  "what's wrong?"?  Try Copyright AT&T.
>
I repeat, Curses is an *INTERFACE*.  I did not suggest stealing source
code; what I suggested was using the same names and interfaces for the
operations that were needed, so that on systems where Curses was
available you would be able to use the existing implementation.

>Besides, curses is seriously buggy in a number of places, like:

Quite irrelevant, as I was not advocating swiping source code, but
adapting an existing *interface*.  In fact (Every system needs one)'s
objections are mostly invalid for this reason.  (Also, he wasn't
describing the current version.)

>Internationalization is hard when most implementations use the 8th bit
>for their own nefariousness (using a short yields 9 attr bits that way).

If you're interested in internationalisation, some of the V.3 utilities
are already customisable (se "isort", for example), and V.4 is really
taking it seriously.  (8 bits just aren't enough.)  The Curses interface
in V.4 is going to be the only reasonably widespread internationalisable
(did I write that?) terminal interface around.  I still expect to loathe
it, but there just isn't anything else on offer.

If people are really worried about the size of programs on 286s, they
should be looking forward to OS/2.  With shared libraries, it is
programs which *don't* use standard interfaces which pay a storage cost!

kpv@ulysses.homer.nj.att.com (Phong Vo[eww]) (09/16/88)

Hi all. I've just been alerted by a friend to this discussion on curses.
Following are a few comments on the posting from Terry Lambert.
He brought up many relevant points about earlier versions of curses.
I sympathize with his frustration. In fact, the same frustration
prompted me a few years back to rewrite curses. The following comments
are germane to this new version of curses that is currently distributed
by the System V folks at Summit.

In article <628@wsccs.UUCP>, terry@wsccs.UUCP (Every system needs one) writes:
> In article <313@quintus.UUCP>, ok@quintus.uucp (Richard A. O'Keefe) writes:
> > In article <65474@sun.uucp> swilson@sun.UUCP (Scott Wilson) writes:
> > >>Who _cares_ how much baggage comes with Curses?
> > >I care, other people care.  Some of us are developing C programs
> > >on machines like the Macintosh where you are trying to fit your
> > >OS stuff, your C programming tools, and your C project onto two
> > >800K floppies.  This is comp.lang.c, not comp.lang.c.on.a.big.machine.
> > >with.megabytes.of.disk.space.and.maybe.paging.  Size is important.
> > >And curses is not universally available.
> 
> Bravo, Scott!

Even on a big machine, keeping down program size is good.
Similarly, even on fast machines, you still want your programs to be efficient.
The version of curses that I wrote accomplished both.
The library efficiency comes from the following considerations:
1. Consolidating similar functions and reuse code whenever they
   make sense. For example, wclear and werase are implemented in
   a single piece of code. This piece of code, in turn, uses
   wclrtoeol to do the actual clearing. You'll be amazed at how
   much code duplication there is in older version of curses.
   This happens both at the user-level functions and at the internal
   curses functions such as subparts of wrefresh.
2. Structuring code so that an application only has to include what
   it uses. For example, if an application does not need function
   key detection for input or using the insert/delete line capabilities
   for screen update, these pieces of codes are not linked with the a.out.
   Believe me, these pieces of code are not trivial in size and complexity.
3. The code structuring, in fact, extends to the overall architecture of
   the library as well. The library conceptually consists of two
   parts. The top part is what you tend to think of as libcurses.a.
   The lower part allows access to either the termcap or the terminfo
   database and to do input/output to the terminal. This means that
   if you don't like curses windows, you don't have to pay for its code.
   But you can still do things like time-out reads and function key
   detections as well as all the ioctl-related functions such as noecho
   or cbreak.
4. Developing new screen update and cursor movement algorithms.
   The old algorithms in the original curses from BSD as well as the
   one in System V.2 curses contain many ad-hoc special case code.
   The new screen update algorithm is more theoretically sound and handles
   capabilities such as insert/delete chars and insert/delete lines more
   gracefully. And yes, magic-cookies terminals such as the HP 26* and
   the TVI950 are all handled correctly and "optimally". Of course,
   with the TVI950 and similar terminals where the cookies actually
   occupy screen space, correctness has to be taken with a grain of salt.

> Besides, curses is seriously buggy in a number of places, like:
> 
> 	XS,XN,AM,SG,UG,GG,tputs(), etc.
>
The problems with magic-cookies, margin etc.  are all taken care of
in the new screen update and cursor movement algorithms.

> 
> I can site specific examples; the one you are probably curious about, is,
> however, tputs().
> 
> 	1) It doesn't necessarily cause an I/O to occur in a single write
> 	   operation.  This is BAD as transparent printing gets more
> 	   popular, and seriously kills paged-screen multiple sessions.
>
Tputs itself does not output anything.
It calls a user-supplied function to output characters. Since your application
supplies this function, it ought to do whatever buffering is necessary to
ensure a single write. The window-level <curses> uses a large buffer for
this purpose.

> 
> 	2) Not all implementations know about pad characters, and instead
> 	   print the numbers on the screen.
> 
> The tgetent() does not malloc() the save area; you have to know how big
> the maximum area is going to be beforehand when you're coding your own
> code; that's bad enough... but if some idiot has a monster termcap/info
> entry, curses can't be made happy without kludges.
> 
This is only a problem with termcap-based curses not terminfo-based versions.
At the risk of being flamed, I'll add that vi initialization procedure is
part of the reason for avoiding malloc-ing when a termcap entry is read.

> Curses depends (according to SVID) on the terminfo file.  This is a kludge.
> 
> 	1) It is not extensible.  It depends on a struct compiled into
> 	   libcurses.
> 
> 	2) It is hard to fix.  Most manufacturers do not provide source.
>
I am not a big fan of terminfo myself but there are advantages in terminfo
beyond termcap. Most of these have been mentioned before by others. I only
emphasizes here that this conversation started partially with the problem of
fat and slow curses. The use of terminfo does speed up an application start-up
time considerably and does reduce the size of the application somewhat.
As I like the flexibility of termcap, my local version of curses provides
support for both termcap and terminfo. In fact, at start-up time, an application
can decide on what database to use.

> 
> 	3) Many terminal definitions are wrong; specifically, SCO Xenix
> 	   is the only system I've seen that has gotten the Wyse-50 and
> 	   the Televideo 950 graphics correct, and I had a lot to do with
> 	   that.  True, it's usually broken in termcap, but at least I
> 	   can fix that.
> 
Have you communicated these problems with Tony Hansen (att!pegasus!hansen)?
He maintains the most up to date termcap/terminfo source that I know of.
I did have a TVI950 and many flavors of the HP26* terminals that I used
to test the screen update algorithm.

> 	4) It will not work with a true VT100 terminal or emualation.
> 	   Since VT100's are probably the most emulated terminal, this
> 	   is stupid, and obviously a result of poor or no testing.  I
> 	   expect a company like AT&T to be able to afford one of each
> 	   of the terminals they say they support, considering what they
> 	   are charging for a liscence.  To get it to work, you have to
> 	   lie and say you are on a 'vt100-nam' or remove the "AM" attr.
> 
As far as I know, curses work as advertised. In fact, I have programs that
people use regularly without problems on their PCs with vt-100 emulation
packages.

> Curses is brain-damaged with windows.  The window implementation is
> bad in that it
> 
> 	1) Does not understand hardware scrolling (though this is more
> 	   a terminfo fault, in that it can not be extended to fix
> 	   this deficiency anyway).
> 
The new update algorithm knows about hardware scrolling to all its gory variations.
This includes all things such as scrolling regions, memory retained above
and below, scroll forward/backward and so on.

> 	2) Can not move a window in the background while leaving another
> 	   in the foreground untouched.  This is the fault of the model
> 	   used to implement the window and it's memory mapping.  Layered
> 	   windows were chosen to avoid "excessive memory allocation" for
> 	   the save buffer area.  The point of diminishing returns, to
> 	   correct this misinformation, is when all windows are n x m or
> 	   larger where n+1 x m+1 is the virtual screen size.
> 
I only understand the first sentence. With SYSV curses, you can use wnoutrefresh
to do a sequence of virtual window refreshes until you get the screen that you
want then call doupdate to get the screen changed. Admittedly this is not the
same as being able to move windows in the same way that windows on bit-map
terminals are moved but it is not hard to implement the bit-map window movement
model on top of the curses model. In fact, I know of at least a few such
implementations. The basic curses model is very useful in appropriate applications.

> There are no field input primitives.
> 
Are you talking about a form-like facility?
There are many packages for doing that. They are implemented on top of curses.
I developed a language called IFS (Interpretive Frame System) to write
form and menu programs. In fact, this work is what got me to rewrite curses.
Older versions were just too buggy and fat and slow to do what I wanted to do.

> Typical code sizes change from:
> 
> 	270k -> 288k
> 	508k -> 527k
> 
> when libcurses  is used instead of libtermcap.  While it is true that
> disk space is no longer a problem on most systems, space on distribution
> media is limited.  This is an 18-19k increase, and can force an additional
> disk if there are several executables and distribution space is already
> tight (it has in 3 cases at our company, due to the target system no
> longer supporting termcap).
> 
With the new curses, the size problem will not be as bad. I don't have specific
numbers but I was told that the new curses is at least 20% smaller than older
ones (except the original BSD version but that does not do much).

> 
> Internationalization is hard when most implementations use the 8th bit
> for their own nefariousness (using a short yields 9 attr bits that way).
> 
> It is ridiculous to think that a company would ship a product *HEAVILY*
> dependant on it's display without writing their own code or buying
> someone elses.
>
The new library is internationalized. It knows all about the European
character sets which are relatively simple. It also knows about Oriental
character sets which have multiple-byte and multiple-column characters.

Now, I would like to comment on the unnecessary bashing of earlier curses
implementations and AT&T. When curses was first built some 10 years ago,
machines were small and slow and the international market was non-existent.
Every bit and byte counts so the library was implemnted to save as much
space as possible. It is unlikely that either Ken Arnold or Mark Horton were
thinking of the Japanese market around that time. In fact, they were rather
clever in making use of these bits and bytes to get the desired functionality.
Only in the past few years that considerations for these other markets
become prominent and we begin to see inadequacies in current software.
People like myself and others (David Korn, Warren Montgomery, Tony Hansen just
to name a few) in AT&T do spend considerable amount of time and effort 
to improve our software and  make them generally applicable.

	Phong Vo, att!ulysses!kpv, 201-582-4869
	AT&T Bell Labs, 600 Mountain Ave, Murray Hill, NJ07974

karl@ddsw1.UUCP (Karl Denninger) (09/17/88)

In article <10608@ulysses.homer.nj.att.com> kpv@ulysses.homer.nj.att.com (Phong Vo[eww]) writes:
>Hi all. I've just been alerted by a friend to this discussion on curses.
>Following are a few comments on the posting from Terry Lambert......
.....

Question for you curses hackers:

Why is it that in a terminfo based implementation that the screen does not
redraw on a "refresh()" call if there are characters stacked by type-ahead?

I've seen this behavior on three different terminfo implementations, so I
assume it's something internal to the design.  The worst part about this
problem is that there is _no way_ to prevent the gagging of output.

I can understand the intent -- to allow type-ahead to be processed, since
you might be able to process faster than the output could be sent to the
terminal over a serial line.  But this behavior makes curses _useless_ for
some interactive applications, as anytime you get ahead of the system, the
output freezes until the machine catches up!

The immediate application is a multiuser game -- which should display the
screen contents after each move.  With termcap curses I get the desired 
behavior.  With terminfo it's unplayable, as the screen just _sits_ there
until type-ahead is exhausted.  Since the game regulates input by use of a
sleep() call (or nap() in those systems which have it), there is _often_
stacked type-ahead waiting.  The result?  You can't see what the @#$# you're
doing!

Is there a work-around for this problem, or a way (other than flushing the
input) to get the output to appear _now_ when I call refresh()?  I haven't
been able to find it.

--
Karl Denninger (ddsw1!karl) Data: (312) 566-8912, Voice: (312) 566-8910
Macro Computer Solutions, Inc.    "Quality solutions at a fair price"

les@chinet.UUCP (Leslie Mikesell) (09/18/88)

In article <1715@ddsw1.UUCP> karl@ddsw1.UUCP (Karl Denninger) writes:

>Why is it that in a terminfo based implementation that the screen does not
>redraw on a "refresh()" call if there are characters stacked by type-ahead?

>I've seen this behavior on three different terminfo implementations, so I
>assume it's something internal to the design.  The worst part about this
>problem is that there is _no way_ to prevent the gagging of output.

The AT&T SysVr3 curses(3X) says that you can use the function
typeahead(fildes) to tell curses to perform its type-ahead check
on some other file instead of stdin or what you passed to newterm().
If fildes is -1, no typeahead checking is done.

The idea is that if you have typed something ahead, you probably aren't
interested in the pending display so it is postponed until the next
time refresh() is called.  In case your version doesn't have the
typeahead() function, you might just call refresh() twice every time
that it is important to update the display.  If it completed on the
first call it shouldn't output anything on the second.

Les Mikesell

kpv@ulysses.homer.nj.att.com (Phong Vo[eww]) (09/18/88)

In article <1715@ddsw1.UUCP>, karl@ddsw1.UUCP (Karl Denninger) writes:
> 
> Why is it that in a terminfo based implementation that the screen does not
> redraw on a "refresh()" call if there are characters stacked by type-ahead?
> 
In many interactive applications (e.g., editors or form/menu systems),
users are not always interested in the intermediate screens,
only in the final screen after a long sequence of typed inputs.
Since these are popular curses applications,
type ahead checking was made the default behavior for curses.

> Is there a work-around for this problem, or a way (other than flushing the
> input) to get the output to appear _now_ when I call refresh()?  I haven't
> been able to find it.
> 
Yes. After initscr(), call typeahead(-1). This turns off the typeahead
checking algorithm (by setting the type ahead file descriptor to -1).