[comp.unix.wizards] printf, data presentation

tony@xenlink.UUCP (Tony Field) (12/30/88)

(I am posting this on comp.lang.c and comp.unix.wizards.  If this is
inappropriate for either group, my mistake.)

I wonder why C i/o functions - including curses - do not provide a simple
method of accepting 'fixed format' screen input?  The following example
illustrates the problem and also shows a simple solution.

Often, a programmer must construct complex data acquisition screens that
have a number of user-enterable fields. For example, a Human Resources
system might need a screen that looks like:

+-----------------------------------------------------------------------------+
|                    H U M A N     R E S O U R C E S                          |
|                                                                             |
|   NAME: ______________________________________       DEPARTMENT: _ __       |
|ADDRESS: __________________________________________                          |
|         __________________________________________                          |
|         __________________________________________                          |
|                                                                             |
|        S.I.N.: ___ ___ ___         PHONE: ___ _______          (RES)        |
|                                                                             |
|MONTHLY BASE SALARY: __________              YEARLY BASE SALARY: __________  |
+-----------------------------------------------------------------------------+

The normal way of solving this problem is to develop special code to
allow the user to traverse the screen.

What the programmer really wants to do is say, "Here is a screen image.
Place the user's data field responses into these variables.". I have seen
many "data windows" packages - mostly in MSDOS - but none of them seems
to follow the spirit of C. In spirit, all formatted display in C should
follow the general conventions of "printf/sscanf".

For example, the Human Resources screen could be presented to the user with
the following type of code:

      wstart (editsub,BLUE,GREEN,GREY,BLUE,BAR);

      wdefine (20,0," H U M A N    R E S O U R C E S ");
      wdefine (0,4,"   NAME: %40s   DEPARTMENT: %1c %3d",hr.name,&hr.dept,&hr.dnumb);
      wdefine (0,5,"ADDRESS: %40s",hr.addr1);
      wdefine (9,6,"%40s",hr.addr2);
      wdefine (9,7,"%40s",hr.addr3);
      wdefine (9,9,"S.I.N.: %-10ld       PHONE: %20s  (res)",&hr.sin,hr.phone);
      wdefine (0,11,"MONTHY BASE SALARY $%10.2lf",&hr.salary);
      wdefine (40,11,"YEARLY BASE SALARY $%10.2plf",&yearly);

      do
      {  wfetch_screen ();
         error_code = edit_user_data (&hr);
      } while (error_code);
      
The function "wstart" prepares the software to accept a new screen
definition. In addition it provides colour (or other) attributes for
prompt and data fields.

The "wdefine" function calls set up the various data fields and places
the various prompts and current contents of the data fields on the
screen. The parameters first specify the x-y screen coordinates, the
formatting string for the prompts and data fields, and the the ADDRESS of
the various data items (like sscanf).

Simple analysis of the format string can easily segregate the "prompt"
information from the formatting description of the data items. In
addition, sufficient information is provided to locate the x-y
coordinate, size, and type of every data field.

After the screen has been defined with "wdefine", a single call to
function "wfetch_screen" can walk the user through the entire screen
structure (even in a user-defined random pattern). When wfetch_screen
returns, the programmer can assume all of the variables have been filled
in by the user. The programmer's error checking routine can be called
until the user's data is error-free.

The mechanism presented above illustrates a screen presentation style
that is familiar to IBM-3270 programmers (and dBase programmers) : i.e.
present a screen to the user, fetch all his responses, then edit the
data.

Simple extensions could be made to allow field-by-field data editing.
This would be more consistent with programming styles on *nix system.
The field-by-field editing also can allow 'dynamic data help' to provide
user with help information.

I feel that C really needs a cleaner method of accepting screen input
than currently provided by printf/curses.  There should be a 'standard
C library' set of functions, consistent with the style of C, that
allow full-screen data presentation.

If any one is interested in this general problem, I would appreciate
their comments.  In addition, I could provide a bunch of C code (that
currently runs under Xenix or QNX) that implements all of the above.

les@chinet.chi.il.us (Leslie Mikesell) (12/30/88)

In article <19@xenlink.UUCP> tony@xenlink.UUCP (Tony Field) writes:

>I wonder why C i/o functions - including curses - do not provide a simple
>method of accepting 'fixed format' screen input?  The following example
>illustrates the problem and also shows a simple solution.
[....]
>If any one is interested in this general problem, I would appreciate
>their comments.  In addition, I could provide a bunch of C code (that
>currently runs under Xenix or QNX) that implements all of the above.

I would like to see something like this but extended so that if the
terminal is actually a PC running a special terminal emulation program
the editing would be handled locally.  The host would just pass the input
form and field parameters and tell the terminal whether it wanted the
the response back by charcter, field or full screen.  I would want to
do this over a network with a unix host, PC's as terminals, with the
users unaware that the application was not running under DOS, but is seems
like something that would be generally useful regardless of the physical
link.  Given the popularity of PC's as terminals, I'm surprised this hasn't
been done (or has it?).

Les Mikesell

is813cs@pyr.gatech.EDU (Cris Simpson) (12/30/88)

In article <19@xenlink.UUCP> tony@xenlink.UUCP (Tony Field) writes:
>I wonder why C i/o functions - including curses - do not provide a simple
>method of accepting 'fixed format' screen input?  The following example
>The normal way of solving this problem is to develop special code to
>allow the user to traverse the screen.
>What the programmer really wants to do is say, "Here is a screen image.
>Place the user's data field responses into these variables.". I have seen
>many "data windows" packages - mostly in MSDOS - but none of them seems
>to follow the spirit of C. In spirit, all formatted display in C should
>follow the general conventions of "printf/sscanf".
>The mechanism presented above illustrates a screen presentation style
>that is familiar to IBM-3270 programmers (and dBase programmers) : i.e.
>present a screen to the user, fetch all his responses, then edit the
>data.
>
>I feel that C really needs a cleaner method of accepting screen input
>than currently provided by printf/curses.  There should be a 'standard
>C library' set of functions, consistent with the style of C, that
>allow full-screen data presentation.
>
>If any one is interested in this general problem, I would appreciate
>their comments.  In addition, I could provide a bunch of C code (that
>currently runs under Xenix or QNX) that implements all of the above.

To me, the best thing about C is that it is no bigger than it has be.
To say that there should be a 'standard C  library' of screen data
functions conflicts with the philosophy, style and practice of C. 

If you need this, there are probably better ways to get it than 
to ask for it to be included in the stdlib. I have no use for it,
but say that I wanted sound functions. Should they be in the 
stdlib? Naah.  I could write some sound functions if my 
box had sound, or I could buy a package that supported it.  
But it is of limited utility to the general world and definitely 
non-portable.


If this is something that dBase does so well, why not use that.  Or try
 a dBase compiler.  The right tools make any job easier.

If you need to drive a nail, don't hit it with a crescent wrench,
it messes up the wrench and doesn't do that good a job, either.



cris

stuart@bms-at.UUCP (Stuart Gathman) (01/03/89)

The static screen presentation wheel has been invented many times over.
There are numerous packages available for purchase or free, many including
source code.  A useful discussion for the net might be what features
could/should be standardized.

The great thing about 'C', is that you can always roll your own.  We
did just that - it is not that big a project and includes pop up windows
and the works.  AT&T curses is so buggy, we had no choice but to
replace it.  The worst curses performance problem is that every character
requires a function call(s).  A low level display string function does 
wonders.  Our screen programs went from 100K with AT&T curses to
30K with BMS curses.  (NOTE, any PD curses is better than AT&T.)

We use a "screen painter"  to define data entry windows.  Dynamic windows
similar to the original posters are also used for things like multiple
choice lists.  Both approaches have advantages.

We have a verify function for each field defined in a table.  This allows
the same application to work in either a full duplex or block 
environment.  Only the field tab library module changes to accomodate.
In full duplex mode, the verify function is called immediately on field
exit.  In block mode, all are called on "ENTER".  This could be 
a run time choice with terminfo/cap extensions to support block mode.

My list of necessary features would include:

	1) both full duplex and block mode support.
	2) user definable formatting and verification.
	3) both painted and dynamic windows.
	4) independent windows
	5) table driven terminal configuration (terminfo,termcap)
	6) dynamic attribute control with good defaults
	7) both WP and DATA style fields
	13) IBM mode to disable type ahead :-)

A good book on the window level is "Ascii display programming in C".
-- 
Stuart D. Gathman	<stuart@bms-at.uucp>
			<..!{vrdxhq|daitc}!bms-at!stuart>

jcbst3@cisunx.UUCP (James C. Benz) (01/04/89)

In article <19@xenlink.UUCP> tony@xenlink.UUCP (Tony Field) writes:
>
>
>(I am posting this on comp.lang.c and comp.unix.wizards.  If this is
>inappropriate for either group, my mistake.)
>
>I wonder why C i/o functions - including curses - do not provide a simple
>method of accepting 'fixed format' screen input?  The following example
>illustrates the problem and also shows a simple solution.

The Perform program released by Informix with the original non-SQL non-4GL
version 3.30 does just that - you feed it a text file with the screen image
you want, and it sets up a data-entry screen for the user.  Although it
is specifically for use with Informix type data files, the concept is one
that I would also like to see in a standard library, because this package
routine often allows the user access to functions that I would prefer to
restrict (like remove of data records) and to functions that are either
confusing or superfluous to the desired application. (like Current, or
the Screen command on one-screen forms).

gpasq@picuxa.UUCP (Greg Pasquariello X1190) (01/04/89)

In article <19@xenlink.UUCP> tony@xenlink.UUCP (Tony Field) writes:
-
-
-I wonder why C i/o functions - including curses - do not provide a simple
-method of accepting 'fixed format' screen input?  The following example
-illustrates the problem and also shows a simple solution.
-

Because this is the function (no bad pun intended) of a library.  You can
chose whatever library that you want that does the job.  If the library is
good enough, or fills a particular niche, it may become "de-facto" standard.

Remember that C provides no I/O.  This needs to be provided by the (operating)
system.

Greg Pasquariello
-- 
=============================================================================
Dirt is the mother o' lunch 	  	Greg Pasquariello AT&T/EDS
					att!picuxa!gpasq  
=============================================================================

vch@attibr.UUCP (Vincent C. Hatem) (01/04/89)

In article <144@bms-at.UUCP>, stuart@bms-at.UUCP (Stuart Gathman) writes:
} :
} :
} :
} and the works.  AT&T curses is so buggy, we had no choice but to
} replace it.  The worst curses performance problem is that every character
} requires a function call(s).  A low level display string function does 
} wonders.  Our screen programs went from 100K with AT&T curses to
} 30K with BMS curses.  (NOTE, any PD curses is better than AT&T.)

Come, come now... AT&T didn't invent it - they stole it from Berkley.

Another wonderful product from Berkley.

;-} ;-} ;-} ;-} ;-} ;-} ;-} ;-} ;-} ;-} ;-} ;-} ;-} ;-} ;-} ;-}

-Vince

cjc@ulysses.homer.nj.att.com (Chris Calabrese[mav]) (01/04/89)

In article <79@attibr.UUCP>, vch@attibr.UUCP (Vincent C. Hatem) writes:
> In article <144@bms-at.UUCP>, stuart@bms-at.UUCP (Stuart Gathman) writes:
> } :
> } and the works.  AT&T curses is so buggy, we had no choice but to
> } replace it.  The worst curses performance problem is that every character
> } requires a function call(s).  A low level display string function does 
> } wonders.  Our screen programs went from 100K with AT&T curses to
> } 30K with BMS curses.  (NOTE, any PD curses is better than AT&T.)
> 
> Come, come now... AT&T didn't invent it - they stole it from Berkley.

Partially true.  While curses was a Berkeley invention, it has been
radically modified at AT&T, including the development of terminfo,
the addition various sub-window routines, support for color, and
amazing speed increases.  The question is, are you comparing an
outdated AT&T version of curses (say sVr2) to a new release of
curses from another company.  Why not try getting a hold of the
sVr3.2 curses?

I'm not trying to be pro-AT&T (I don't even work for them, I'm
a contractor), I just think their _current_ product is good, and
that you're possibly not referring to it.

Besides, who uses a character terminal any more :-) :-) :-) :-)
-- 
	Christopher J. Calabrese
	AT&T Bell Laboratories
	att!ulysses!cjc		cjc@ulysses.att.com

knudsen@ihlpl.ATT.COM (Knudsen) (01/05/89)

Speaking of libraries and interactive screen programs,
it strikes me as criminal negligence that hardly any C standard
libs include the inkey() function, which means "check whether
a char has been typed on the keyboard; if so, return it;
else return \0 (or whatever).  DO NOT BLOCK."

Even a blocking version (that would return a char once typed,
without waiting for a newline) would be useful.

Most OSes make the inkey() function possible, but hardly easy.
I figured out how to do it in OS9, and someday I may borrow
a chapter 7 of the sys-adm's U**X manual long enuf to write
one for System V.  I know it takes a lot of ioctl() bashing.
I have also done the blocking version in U**X, using fcntl().

My point is that some guru should have figured out how to do
inkey() on the OS in question and put this in the library.
Then ordinary programmers wouldn't have to figure it out
for the zillionth time.
[Given that U**X was born on DEC machines with full-duplex
TTYs, I'm surprised that the C library didn't get inkey()
early on.  I guess VI and EMACS didn't come till much later.]

Anyway, it's the need for such functions that often keeps interactive
applications from using the buffered (f-names) I/O fcns.

Ironically, inkey() is built into every "toy" computer with
BASIC in ROM.  The joys of having no OS...
-- 
Mike Knudsen  Bell Labs(AT&T)   att!ihlpl!knudsen
"Lawyers are like nuclear bombs and PClones.  Nobody likes them,
but the other guy's got one, so I better get one too."

gwyn@smoke.BRL.MIL (Doug Gwyn ) (01/05/89)

In article <11064@ulysses.homer.nj.att.com> cjc@ulysses.homer.nj.att.com (Chris Calabrese[mav]) writes:
>Besides, who uses a character terminal any more :-) :-) :-) :-)

Exactly.  That's why I don't support standardization of curses-like
interfaces.  It's an idea whose time has gone.

peter@ficc.uu.net (Peter da Silva) (01/05/89)

In article <79@attibr.UUCP>, vch@attibr.UUCP (Vincent C. Hatem) writes:
> In article <144@bms-at.UUCP>, stuart@bms-at.UUCP (Stuart Gathman) writes:
> } and the works.  AT&T curses is so buggy, we had no choice but to
> } replace it...

> Come, come now... AT&T didn't invent it - they stole it from Berkley.

The AT&T implementation and the Berkeley implementation have to be quite
different internally. The BSD version uses the TERMCAP database, and the
AT&T version uses the TERMINFO database. These databases are similar in
goals, but quite different in design and implementation.
-- 
Peter da Silva, Xenix Support, Ferranti International Controls Corporation.
Work: uunet.uu.net!ficc!peter, peter@ficc.uu.net, +1 713 274 5180.   `-_-'
Home: bigtex!texbell!sugar!peter, peter@sugar.uu.net.                 'U`
Opinions may not represent the policies of FICC or the Xenix Support group.

wen@husc4.HARVARD.EDU (A. Wen) (01/05/89)

In article <8332@ihlpl.ATT.COM> knudsen@ihlpl.ATT.COM (Knudsen) writes:
>Most OSes make the inkey() function possible, but hardly easy.
>I know it takes a lot of ioctl() bashing.
...
>My point is that some guru should have figured out how to do
>inkey() on the OS in question and put this in the library.
>Then ordinary programmers wouldn't have to figure it out
>for the zillionth time.

But it's very, very easy:

(with cbreak mode set)

#include <ioctl.h>

char inkey()
{
	int count=0;

	ioctl(0,FIONREAD,&count);  
	return(count?getchar():NULL);
}


A. Wen          wen@husc4.HARVARD.EDU  wen@husc4.BITNET  {seismo!harvard!husc4}

friedl@vsi.COM (Stephen J. Friedl) (01/05/89)

In article <11064@ulysses.homer.nj.att.com> cjc@ulysses.homer.nj.att.com (Chris Calabrese[mav]) writes:
>Besides, who uses a character terminal any more :-) :-) :-) :-)

In article <9281@smoke.BRL.MIL>, gwyn@smoke.BRL.MIL (Doug Gwyn ) writes:
> Exactly.  That's why I don't support standardization of curses-like
> interfaces.  It's an idea whose time has gone.

Doug, you are living in a dream world, one full of idealistic fantasy.
You may like your Blit, but for every one of you, there are at least
50,000 people with Wyse 50s at their desks.  For the majority of these
people, a bitmapped interface would be massive overkill.

     No :-)

     Steve

-- 
Stephen J. Friedl        3B2-kind-of-guy            friedl@vsi.com
V-Systems, Inc.        I speak for me only      attmail!vsi!friedl
Santa Ana, CA  USA       +1 714 545 6442    {backb

daveh@marob.MASA.COM (Dave Hammond) (01/05/89)

In article <9281@smoke.BRL.MIL> Doug Gwyn writes (re curses-based interfaces):

>  It's an idea whose time has gone.

Are you saying that a (relatively) high-priced, ethernet-connected
graphical display should be installed for every office manager, production
assistant or data-entry operatory who performs simple data management
tasks?  Or perhaps that applications which don't require bitmap displays
and mice would not benefit from a standardized set of menu, window and form
management tools?

I realize this is not a popular concept, but there is a large segment of
the Unix population which is *not* involved with cutting-edge design and
engineering tasks, but merely doing their mundane, daily work on a Unix
machine.

[ perhaps we should reissue teletypes for such trailing-edge tasks :-) ]

--
Dave Hammond
...!uunet!masa.com!{marob,dsix2}!daveh

daveh@marob.MASA.COM (Dave Hammond) (01/05/89)

In article <8332@ihlpl.ATT.COM> knudsen@ihlpl.ATT.COM (Knudsen) writes:
>Speaking of libraries and interactive screen programs,
>it strikes me as criminal negligence that hardly any C standard
>libs include the inkey() function, which means "check whether
>a char has been typed on the keyboard; if so, return it;
>else return \0 (or whatever).  DO NOT BLOCK."

If I understand your need, the fcntl VMIN and VTIM parameters may
help.  If you set VMIN=0 and VTIM>0, read() returns immediately
if characters are available, or in VTIM 10th-secs if the queue is dry.

I use VMIN=0,VTIM=1 to grab the next char, or return immediately if
none is available.

>Even a blocking version (that would return a char once typed,
>without waiting for a newline) would be useful.

Try reading with VMIN=1,VTIM=0.  This is akin to the Berkeley CBREAK mode.

--
Dave Hammond
...!uunet!masa.com!{marob,dsix2}!daveh

gwyn@smoke.BRL.MIL (Doug Gwyn ) (01/06/89)

In article <443@marob.MASA.COM> daveh@marob.masa.com (Dave Hammond) writes:
-In article <9281@smoke.BRL.MIL> Doug Gwyn writes (re curses-based interfaces):
->  It's an idea whose time has gone.
-Are you saying that a (relatively) high-priced, ethernet-connected
-graphical display should be installed for every office manager, production
-assistant or data-entry operatory who performs simple data management
-tasks?  Or perhaps that applications which don't require bitmap displays
-and mice would not benefit from a standardized set of menu, window and form
-management tools?
-I realize this is not a popular concept, but there is a large segment of
-the Unix population which is *not* involved with cutting-edge design and
-engineering tasks, but merely doing their mundane, daily work on a Unix
-machine.
-[ perhaps we should reissue teletypes for such trailing-edge tasks :-) ]

Fine, if you make it a Teletype model 630.  If an employee isn't worth
investing $2K for dramatically improved productivity then I feel sorry
for the employer.

Even mickey-mouse IBM PCs can support much better working environments
than traditional CRT forms.

cjc@ulysses.homer.nj.att.com (Chris Calabrese[mav]) (01/06/89)

In article <443@marob.MASA.COM>, daveh@marob.MASA.COM (Dave Hammond) writes:
> In article <9281@smoke.BRL.MIL> Doug Gwyn writes (re curses-based interfaces):
> 
> >  It's an idea whose time has gone.
> 
> Are you saying that a (relatively) high-priced, ethernet-connected
> graphical display should be installed for every office manager, production
> assistant or data-entry operatory who performs simple data management
> tasks?  Or perhaps that applications which don't require bitmap displays
> and mice would not benefit from a standardized set of menu, window and form
> management tools?

First off, these machines are now available for under $2000.
Examples are Acer's Xerbra, a terminal with an ethernet connector and
an X server in rom, and Atari ST's running NeWS with some help from
a BSD box.

A few years ago, before the school I was going to ever
dreamed of multi window terminals and workstations, everyone
has at least two terminals on their desk (yes, I can switch
between two keyboards - one in my lap and one on the desk -
just as fast as between windows).  Given that decent terminals
cost at least $500, this isn't so much of a difference for the
added flexibility that windows give you.

> I realize this is not a popular concept, but there is a large segment of
> the Unix population which is *not* involved with cutting-edge design and
> engineering tasks, but merely doing their mundane, daily work on a Unix
> machine.

And there are lots of old terminals sitting around just waiting
to be used (around here there are even a few bitmap machined collecting
dust), but the price of bitmapped workstations keep falling fast enough
to make it unreasonable to assume the necessity of additional
support for dumb terminals in standard libraries.

I'm not saying there's no need for such abilities, Bell Labs has
devoted quite a bit of effort in this area in the past, but
there are packages available to do these things already.
I seem to remember a curses based widget library posted to
the net a couple of months ago.
-- 
	Christopher J. Calabrese
	AT&T Bell Laboratories
	att!ulysses!cjc		cjc@ulysses.att.com

bruce@blue.gwd.tek.com (Bruce Robertson) (01/07/89)

> Fine, if you make it a Teletype model 630.  If an employee isn't worth
> investing $2K for dramatically improved productivity then I feel sorry
> for the employer.

Please explain how a $2K model 630 is so much better than a $350
Wyse-50 for someone doing, say, database entry all day.  Another
example: factory floor diagnostics, which can benefit from screen
manipulation, but don't really gain anything from graphics.
--

	Bruce Robertson
	bruce@blue.gwd.tek.com

guy@auspex.UUCP (Guy Harris) (01/07/89)

>If I understand your need, the fcntl VMIN and VTIM parameters

"ioctl(TCSETA)" and company, not "fcntl".

>may help.  If you set VMIN=0 and VTIM>0, read() returns immediately
>if characters are available, or in VTIM 10th-secs if the queue is dry.

This works on UNIXes that have VMIN and VTIME (S3, S5, SunOS 4.0, some
others).  It doesn't work on older UNIXes, or non-UNIX systems; I think
he wanted a routine that would, on all (or, at least, most) systems, do
what was appropriate on that system (whether UNIX or not).

>I use VMIN=0,VTIM=1 to grab the next char, or return immediately if
>none is available.

Try VTIME=0 instead (although this may not work under S3); that will
return immediately, rather than after 1/10 second (which VTIME=1 does).

>>Even a blocking version (that would return a char once typed,
>>without waiting for a newline) would be useful.
>
>Try reading with VMIN=1,VTIM=0.  This is akin to the Berkeley CBREAK mode.

Actually, the equivalent of turning on V7 CBREAK (not Berkeley - they
didn't invent CBREAK, AT&T did) is turning ICANON off and setting VMIN
to 1 and VTIME to 0.  VMIN and VTIME are meaningful only if ICANON is off.

jfh@rpp386.Dallas.TX.US (John F. Haugh II) (01/07/89)

In article <992@vsi.COM> friedl@vsi.COM (Stephen J. Friedl) writes:
>In article <11064@ulysses.homer.nj.att.com> cjc@ulysses.homer.nj.att.com (Chris Calabrese[mav]) writes:
>>Besides, who uses a character terminal any more :-) :-) :-) :-)
>
>In article <9281@smoke.BRL.MIL>, gwyn@smoke.BRL.MIL (Doug Gwyn ) writes:
>> Exactly.  That's why I don't support standardization of curses-like
>> interfaces.  It's an idea whose time has gone.
>
>Doug, you are living in a dream world, one full of idealistic fantasy.
>You may like your Blit, but for every one of you, there are at least
>50,000 people with Wyse 50s at their desks.  For the majority of these
>people, a bitmapped interface would be massive overkill.

No joke.  We have about 50 ASCII terminals and one 4014/VT 220 clone.
The 4014-clone is great fun but no one wants to use it.  Graphis at
19.2KB are SLOW.

Our primary usage for UNIX is data entry.  That's it.  Our user's don't
care if they are running UNIX or VMS or whatever.  Most of them don't
even know what an operating system is.  Some of them think UNIX is
worse than MS-DOS because it doesn't run Lotus 1-2-3. 

Sorry, but there are MANY dumb-old ASCII tubes out there.  My Wyse-50
is not the only one.  Sure, I'd love to drag the Visual 603 into my
office and use it, except I like my Wyse-50 just fine.  I don't do
windows ;-)
-- 
John F. Haugh II                        +-Quote of the Week:-------------------
VoiceNet: (214) 250-3311   Data: -6272  |"Now with 12 percent less fat than
InterNet: jfh@rpp386.Dallas.TX.US       | last years model ..."
UucpNet : <backbone>!killer!rpp386!jfh  +--------------------------------------

flint@gistdev.UUCP (01/07/89)

I've found ioctl to be about the least portable thing in UNIX.  (FIONREAD
isn't in the SVID, or at least I couldn't find it in TERMIO(BA_ENV) or
IOCTL(BA_OS), so if it is in SVID & I missed it, I'd appreciate being
enlightened.) 

I think the main thrust of the inkey() request is requesting a _portable_
way to do a non-blocking read.  I'd like to extend the request one step
further, to request a _portable_ way to do efficient timed reads.  (I don't
see any reason why inkey() can't do both: inkey(0) would be non-blocking,
while inkey(10) would block until either a key arrived or 1 second
elapsed.)  You can't do this with ioctl() right now, simply because ioctl()
is too slow to call on every keypress.  (For example, if I want my user
to type as many keys as they want to within 10 seconds, and then evaluate
that amount of input, I'm stuck: I have to change the timelimit with each
successive keypress to be "10 - time_used_so_far", and the only way to do
so is with an incredibly slow ioctl() call on each keypress.  Some Guru
out there might know some neat way to do this I haven't heard about:
if you know how to do it in Sys V without having to go way out of your
way with something like writing your own device driver, I'd like to hear
your solution.)

Flint Pellett, Global Information Systems Technology, Inc.
1800 Woodfield Drive, Savoy, IL  61874     (217) 352-1165
INTERNET: flint%gistdev@uxc.cso.uiuc.edu
UUCP:     {uunet,pur-ee,convex}!uiucuxc!gistdev!flint

peter@ficc.uu.net (Peter da Silva) (01/07/89)

In article <9281@smoke.BRL.MIL>, gwyn@smoke.BRL.MIL (Doug Gwyn ) writes:
> In article <11064@ulysses.homer.nj.att.com> cjc@ulysses.homer.nj.att.com (Chris Calabrese[mav]) writes:
> >Besides, who uses a character terminal any more :-) :-) :-) :-)
> 
> Exactly.  That's why I don't support standardization of curses-like
> interfaces.  It's an idea whose time has gone.

When there's a recognised standard for bitmapped displays, then you can
say the need for curses is gone. In the meantime, curses is the best
tool we have... it's the only one that lets you do the job (presenting
2-d textual data in a machine-independent way).

STDWIN is a nice start at a replacement, but it's pretty complex.
-- 
Peter da Silva, Xenix Support, Ferranti International Controls Corporation.
Work: uunet.uu.net!ficc!peter, peter@ficc.uu.net, +1 713 274 5180.   `-_-'
Home: bigtex!texbell!sugar!peter, peter@sugar.uu.net.                 'U`
Opinions may not represent the policies of FICC or the Xenix Support group.

peter@ficc.uu.net (Peter da Silva) (01/07/89)

From my recollection of BASIC, INKEY$ has two main uses:

	(1) Enabling a clean abort of a running compute-bound
	    program.

	(2) Busy-waiting for a time-interval.

For case 1, UNIX provides signal handlers. For case 2, a read-with-timeout
is more useful. Luckily, UNIX provides this as well. For long timeouts, it
reduces to the case of a signal handler. For short timeouts, you need the
USG termio, and set VMIN and VTIME.

	(3) Terminal emulators.

For this case, you're better off with a multiway wait or two cooperating
processes.

Using an inkey$ type call to do this will just get you a bad name as a system
hog. We just had to rip code like this out of microEmacs last year some
time.
-- 
Peter da Silva, Xenix Support, Ferranti International Controls Corporation.
Work: uunet.uu.net!ficc!peter, peter@ficc.uu.net, +1 713 274 5180.   `-_-'
Home: bigtex!texbell!sugar!peter, peter@sugar.uu.net.                 'U`
Opinions may not represent the policies of FICC or the Xenix Support group.

jb@aablue.UUCP (John B Scalia) (01/07/89)

In <8332@ihpl.ATT.COM> Mike Knudsen makes a request for an INKEY type of
function similar to what is found in most BASICs.

The following code should solve your problem. It allows an INKEY() type
function that allows for multiple returns (ie. function keys), timeout if
user does not press a key, and the ability to wait forever if delay is given
as 0 :-) and the user must make some input. It will also trap every keyboard
stroke I've ever managed to give it. (At least I've not had a problem.)

--------- Cut here ----------
#include <termio.h>
#include <ctype.h>

int key_ret(deft, work)			/* Generic Keyboard input like inkey */
int 	deft;				/* Number of seconds to delay */
char	work[];				/* character string to return result */
{
	struct termio oldterm, curterm;
	int	timer, ret_code;

	timer = deft * 10;		/* timer = # of seconds to wait */

	if (ioctl (0, TCGETA, &curterm) == -1)
		return(-1);		/* Not a terminal, abort */

	oldterm = curterm;

	curterm.c_lflag &= ~ICANON;	/* canonical processing off */

	if (timer == 0)
		curterm.c_cc[VMIN] = 1;
	else {
		curterm.c_cc[VTIME] = timer;
		curterm.c_cc[VMIN] = 0;
	}
	ioctl (0, TCSETA, &curterm);

	ret_code = read (0, work, 10);

	ioctl (0, TCSETA, &oldterm);	/* restore terminal to old settings */
	return (ret_code);
}
# End of function ----------------------

This works only if your function or definable keys produce less than 10
characters, of course you may change this to any number you'd want at the
read(n,C,10) statement. Please no flames about style, etc. I wrote this so
long ago I almost forgot where in fact I had put it.

bzs@Encore.COM (Barry Shein) (01/08/89)

From: friedl@vsi.COM (Stephen J. Friedl)
>In article <9281@smoke.BRL.MIL>, gwyn@smoke.BRL.MIL (Doug Gwyn ) writes:
>> Exactly.  That's why I don't support standardization of curses-like
>> interfaces.  It's an idea whose time has gone.
>
>Doug, you are living in a dream world, one full of idealistic fantasy.
>You may like your Blit, but for every one of you, there are at least
>50,000 people with Wyse 50s at their desks.  For the majority of these
>people, a bitmapped interface would be massive overkill.

I agree with Doug, you might be the one in a dream world.

The point is investing the effort (read $$) in redoing the entire
curses package, having it verified and accepted and getting it into
common use takes a lot of time and money. I could stop right here and
say if you're too cheap to buy new terminals why in the world would I
cater to your needs for new software (ie. poverty sucks.) Better to
learn to live with the current dumb terminal technology then wish
(dream?) that someone else will invest that kind of effort.

But the real point is that graphically oriented displays are coming
down in price rapidly in the form of things like X terminals. There's
already at least one brand selling for under $1K, PCs running decent
graphical interfaces to remote systems should be commonplace soon and
a floppy based, 640K, 286 PC is around $1K (ie. enough to run as a
bitmapped-style terminal), all pretty close to dumb terminal prices
and getting closer.

Even very good (eg. 1Kx1K) X terminals are around $2K and I'll happily
predict will approach $1K in a year or so, probably before the curses
rewrite got out the door and into applications. Note that they're
running both serial and ethernet interfaces.

BUT, you ask, why would I throw out all those dumb terminals and
replace them with these? It doesn't cost me anything (other than
maintenance) to just keep my old stuff?!

The answer is tautological but true: Software.

Do you really want to buy *new* dumb terminals as you expand? Do you
doubt that these new terminal users are going to be bringing in a
whole new world of software which exploits these new terminals?

How long will you want to support two incompatible software bases,
buying the latest release of two new (wordprocessors, spreadsheets,
editors, etc) every year and dealing with training and problems on
both systems? When will the economics of that turn around and bite
you?

Put simply, try using an old paper terminal for a while and see how
many needed tools don't even exist anymore or can't be bought (well,
unix is pretty good at this, but only for the most basic chores, it
certainly was frozen on this technology around a decade ago.)

What happened to all the old paper terminals? We all threw them away,
I remember seeing about 100 of them hauled away as junk a couple of
years ago where I worked, perfectly good decwriter II's I would have
killed for in 1978.

I lived thru it with paper->crt's and people said the same sort of
things (heck, I lived thru punch cards -> paper/interactive terminals,
one dept STILL insisted on getting all their data on punch cards for
years because, well, you could FEEL it or something.) I remember
getting my head chopped off once for delivering an application that
required a CRT and wouldn't work on a paper terminal, I think they
called me a dreamer to think every tom, dick and harry would have a
crt, ever. I think Lear Siegler introduced their $795 ADM-3A around
three months later and that was the end of that argument.

Besides, you see, NAIVE users prefer paper terminals because it lets
them look back at what they did and re-enter things if necessary, only
a sophisticated programmer-type can deal with things running off the
screen all the time (anyone remember that argument? Ah, the naive
user, s/he always wins the battle...)

	-Barry Shein, ||Encore||

bill@twwells.uucp (T. William Wells) (01/08/89)

In article <915@husc6.harvard.edu> wen@husc4.UUCP (A. Wen) writes:
: #include <ioctl.h>
:
: char inkey()
: {
:       int count=0;
:
:       ioctl(0,FIONREAD,&count);
:       return(count?getchar():NULL);
: }

Unix chauvinist!

Not only that, but it's wrong. The function had better have a return
value of int and return EOF or some other value that is guaranteed to
not be a valid character.

And it's not going to work if the attached terminal is line oriented.
Presuming, of course, that the programmer has verified that the
opened file really is a terminal....

The inkey function is almost never as trivial is y'all would like.
When it can be done at all.

---
Bill
{ uunet!proxftl | novavax } !twwells!bill

ka@june.cs.washington.edu (Kenneth Almquist) (01/09/89)

cjc@ulysses.homer.nj.att.com (Chris Calabrese[mav]) writes:
> While curses was a Berkeley invention, it has been radically modified
> at AT&T, including the development of terminfo, ...

Well, my memory is pretty fuzzy here, but I was under the impression that
AT&T had nothing to do with the original development of the terminfo version
of curses, although Mark Horton did a lot of work on it after AT&T picked
up the code.  I recall that the code was copyrighted by Pavel Curtis (or
some such person), and if it had been developed by AT&T then AT&T or Bell
Labs would be the owner of the copyright.  Anyone know for sure?
				Kenneth Almquist

orion@nuchat (Roland Dunkerley) (01/09/89)

In article <8800006@gistdev>, flint@gistdev writes:
>
>I've found ioctl to be about the least portable thing in UNIX.  (FIONREAD
>isn't in the SVID, or at least I couldn't find it in TERMIO(BA_ENV) or
>IOCTL(BA_OS), so if it is in SVID & I missed it, I'd appreciate being
>enlightened.) 
This is true, System V R3 provides (non-portable) functional
equivalants to FIONREAD and the select() call but, it only works on
streams devices...  Maybe R4 will get it right?
>
>  .....  (For example, if I want my user
>to type as many keys as they want to within 10 seconds, and then evaluate
>that amount of input, I'm stuck: I have to change the timelimit with each
>successive keypress to be "10 - time_used_so_far", and the only way to do
>so is with an incredibly slow ioctl() call on each keypress.  Some Guru
>out there might know some neat way to do this I haven't heard about:
>if you know how to do it in Sys V without having to go way out of your
>way with something like writing your own device driver, I'd like to hear
>your solution.)
how about the following:

catch()
{
	signal ( SIGINT, catch );
	signal ( SIGQUIT, catch );
	signal ( SIGALRM, catch );
	alarm(0);
}
/* ...... */
        catch();

	alarm(10);
	if( count=read(0, &buffer, buffer_size)==-1 )
	{
	    alarm(0);
	    /* Handle failure */
	}
        
I think this is portable and should achieve the desired result.  We
use this in the autobaud section of our local getty.
>
>Flint Pellett, Global Information Systems Technology, Inc.
>1800 Woodfield Drive, Savoy, IL  61874     (217) 352-1165
>INTERNET: flint%gistdev@uxc.cso.uiuc.edu
>UUCP:     {uunet,pur-ee,convex}!uiucuxc!gistdev!flint
Roland Dunkerley III
*** (orion@nuchat.UUCP)  (uunet.UU.NET!nuchat!orion)
*** South Coast Computing Services
*** We service Publicly Redistributable software - reasonable rates
*** Inquire within

piet@ruuinf (Piet van Oostrum) (01/10/89)

In article <8800006@gistdev>, flint@gistdev writes:

          to request a _portable_ way to do efficient timed reads. 

Here is a routine I have used for this: It is robust in that it allows
other sleep/alarms in the same program. There's also a routine to do a
timed open (e.g. for terminal lines):


int oldalarm ;
int newalarm ;
int (*oldsig)();

timed_read_alarm()
{
	signal (SIGALRM, oldsig);
	if ( oldalarm != 0 ) {
	  if (oldalarm <= newalarm) kill (getpid(), SIGALRM);
	  else alarm (oldalarm-newalarm);
	} else alarm(0);
	oldalarm = newalarm = 0;
}

timed_read (fd, buf, size, time)
int fd, size, time; char *buf;
{
	long i, rl;
#ifdef BSD
	sleep (time);
	ioctl (fd, FIONREAD, &rl);
	if (rl >= size) rl = size-1;
	if (rl > 0) rl = read (fd, buf, rl);
#else	
	newalarm = time;
	oldalarm = alarm (10000);
	oldsig = signal (SIGALRM, timed_read_alarm);
	sleep (time-1);
	alarm (1);
	rl = (read (fd, buf, size-1));
	if (newalarm != 0) timed_read_alarm();
#endif	
	return (rl);
}

FILE *timed_open (dev, time)
char* dev; int time;
{
        FILE *fw = NULL;
  	newalarm = time;
	oldalarm = alarm (10000);
	oldsig = signal (SIGALRM, timed_read_alarm);
	alarm (time);
	fw = fopen (dev, "w+");
	if (newalarm != 0) timed_read_alarm();
	return (fw);
}
-- 
Piet van Oostrum, Dept of Computer Science, University of Utrecht
Padualaan 14, P.O. Box 80.089, 3508 TB Utrecht, The Netherlands
Telephone: +31-30-531806        UUCP: ...!mcvax!hp4nl!ruuinf!piet

jbayer@ispi.UUCP (Jonathan Bayer) (01/13/89)

In article <11067@ulysses.homer.nj.att.com> cjc@ulysses.homer.nj.att.com (Chris Calabrese[mav]) writes:
>In article <443@marob.MASA.COM>, daveh@marob.MASA.COM (Dave Hammond) writes:
>> 
>> Are you saying that a (relatively) high-priced, ethernet-connected
	[ deleted ]
>
>First off, these machines are now available for under $2000.
>Examples are Acer's Xerbra, a terminal with an ethernet connector and
>an X server in rom, and Atari ST's running NeWS with some help from
>a BSD box.


Sorry.  I can't justify the cost to my customers to spend upwards of $ 2000
per terminal when the cost of a regular character-oriented terminal is
now around $ 300.  There are many applications around which do not have
or need any graphics abilities.  There is no need to run them on a
bit-mapped terminal.  Additionally, there are many systems out in the
field in which the users are using only one or two applications.  If
these applications are character oriented why should they have to spend
the money for an expensive terminal.

	The difference in cost is between $ 1000 and $ 1500.  When you
multiply this by the number of terminals in an office, the cost starts
to become prohibitive.

JB

-- 
Jonathan Bayer				"The time has come," the Walrus said...
Intelligent Software Products, Inc.	
19 Virginia Ave.				...uunet!ispi!jbayer
Rockville Centre, NY   11570	(516) 766-2867	jbayer@ispi

allbery@ncoast.UUCP (Brandon S. Allbery) (01/14/89)

As quoted from <8800006@gistdev> by flint@gistdev.UUCP:
+---------------
| way to do a non-blocking read.  I'd like to extend the request one step
| further, to request a _portable_ way to do efficient timed reads.  (I don't
| see any reason why inkey() can't do both: inkey(0) would be non-blocking,
| while inkey(10) would block until either a key arrived or 1 second
| elapsed.)  You can't do this with ioctl() right now, simply because ioctl()
| is too slow to call on every keypress.  (For example, if I want my user
| to type as many keys as they want to within 10 seconds, and then evaluate
| that amount of input, I'm stuck: I have to change the timelimit with each
| successive keypress to be "10 - time_used_so_far", and the only way to do
| so is with an incredibly slow ioctl() call on each keypress.  Some Guru
+---------------

Under System V, as you requested, set VMIN to the maximum number of
characters you want returned (beware, it's a char and some systems use
signed chars; in other words, the maximum portable VMIN is 127) and VTIME to
the timeout in 10'ths of a second.  Be warned that VTIME == 1 is treated the
same as VTIME == 0 and means no timeout (and that the same signed char
argument applies to VTIME).  [VMIN == minimum number of characters to
satisfy request, i.e. return before the timeout if this many characters have
been received.]

At least *some* System V's will treat VMIN == 0, VTIME == 0 as the inkey()
function originally requested.

As mentioned by others, inkey() is a horrible CPU hog.  (It works on
singleuser systems because they can busyloop waiting for a character without
stealing CPU time from other processes.)  Avoid it whenever possible; the
only possible use I can think of for it that won't bring a system to its
knees is to spot-check for characters in order to interrupt something.  For
example, some versions of curses can be configured to abort a refresh() if a
keysoke is detected, e.g. for an editor.  (Jove does this too -- but does
*not* busy loop, it's doing useful work [redrawing the screen] between calls,
and it goes back to a blocking read after the redraw is completed.)

I *hope* that POSIX is dealing with this.

++Brandon
-- 
Brandon S. Allbery, comp.sources.misc moderator and one admin of ncoast PA UN*X
uunet!hal.cwru.edu!ncoast!allbery		    ncoast!allbery@hal.cwru.edu
 ncoast is registering as "ncoast.org" -- watch for the official announcement!
      Send comp.sources.misc submissions to comp-sources-misc@<backbone>.

guy@auspex.UUCP (Guy Harris) (01/14/89)

>At least *some* System V's will treat VMIN == 0, VTIME == 0 as the inkey()
>function originally requested.

In the code as distributed by AT&T, reads with VMIN == 0, VTIME == 0 are
non-blocking reads, and reads with VMIN == 0, VTIME == 10 wait for up to
1 second, or until a character arrives.  I would hope *all* System V's
work that way, but it's conceivable some are broken.... 

From the SunOS 4.0 TERMIO(4) (it implements an S5 superset - this part
is not a superset, though, S5 does the same stuff):

  Case C: MIN = 0, TIME > 0
     In this case, since MIN = 0, TIME no  longer  represents  an
     intercharacter timer.  It now serves as a read timer that is
     activated as soon as a read() is done.  A read is  satisfied
     as  soon as a single character is received or the read timer
     expires.  Note: in this case if the timer expires, no  char-
     acter  will  be returned.  If the timer does not expire, the
     only way the read can be satisfied  is  if  a  character  is
     received.  In this case the read will not block indefinitely
     waiting for a character - if no character is received within
     TIME*.10  seconds after the read is initiated, the read will
     return with zero characters.

  Case D: MIN = 0, TIME = 0
     In this case return is immediate.  The minimum of either the
     number  of  characters requested or the number of characters
     currently available will be  returned  without  waiting  for
     more characters to be input.

>I *hope* that POSIX is dealing with this.

POSIX specifies an S5-like tty driver, with S5-style behavior for VMIN
and VTIME. 

paul@athertn.Atherton.COM (Paul Sander) (01/15/89)

In article <9281@smoke.BRL.MIL>, gwyn@smoke.BRL.MIL (Doug Gwyn ) writes:
> In article <11064@ulysses.homer.nj.att.com> cjc@ulysses.homer.nj.att.com (Chris Calabrese[mav]) writes:
> >Besides, who uses a character terminal any more :-) :-) :-) :-)
> 
> Exactly.  That's why I don't support standardization of curses-like
> interfaces.  It's an idea whose time has gone.

Hey, wait a minute.  There are an awful lot of people still using character
terminals.  Some of my company's customers rely on them.  I've seen
installations where literally hundreds of programmers have had to share
bitmap terminals that could be counted on the knuckles of one finger.
No joke!  And they make up for it by using ASCII terminals.  And I make
my living developing user interfaces for these people.

There used to be a saying that "not all the world's a VAX."  Perhaps we
should also remember that "not all the world's a Sun/Apollo/Mac/insert-
favorite-desktop-workstation-with-bitmap-terminal-here."
-- 
Paul Sander        (408) 734-9822       | Do YOU get nervous when a
paul@Atherton.COM                       | sys{op,adm,prg,engr} says
{decwrl,sun,hplabs!hpda}!athertn!paul   | "oops..." ?