[comp.unix.questions] How to get a function key in BSD curses

bll@seer.UUCP (Brad Lanam) (06/27/90)

    Is there some easy way to get a function key using Berkeley curses?
I don't have access to the documentation, and the O'Reilly "curses" book
doesn't mention anything about the special keys.

    If there is no easy way, do I a) read the termcap entry, pull
out the sequences for the function keys I need, and watch for them
(is this an esc [ A...)? or b) figure out what values are returned
for the special keys and hard code those values into the program?

    Please E-mail.  Thanx
    -- Brad

--
Until the next disk seek...
   -- Brad Lanam    ...!uunet!{seeker|unisoft}!seer!bll   bll@seer.uucp

-- 
Until the next disk seek...
   -- Brad Lanam    ...!uunet!{seeker|unisoft}!seer!bll    bll@seer.uucp

greg@gagme.chi.il.us (Gregory Gulik) (06/29/90)

In article <502@seer.UUCP> bll@seer.UUCP (Brad Lanam) writes:
>
>    Is there some easy way to get a function key using Berkeley curses?
>I don't have access to the documentation, and the O'Reilly "curses" book
>doesn't mention anything about the special keys.

Use the keypad(win,bf) function.

For example, I always do:	keypad(stdscr,1);
to turn on keypad mode.

Then, you can use the getch() function to read the keys in.  Look
at your system's curses.h file for the key definitions.  Mine has
a lot of comments explaining what they are.

Oh, you may want to call cbreak() to get into one-key-at-a-time
mode.

-greg

-- 
Gregory A. Gulik					Call Gagme, a public
	greg@gagme.chi.il.us  ||  ...!gagme!greg	access UNIX system at
	||  gulik@depaul.edu				(708) 318-7133

leo@ehviea.ine.philips.nl (Leo de Wit) (06/29/90)

In article <520@gagme.chi.il.us> greg@gagme.chi.il.us (Gregory Gulik) writes:
|In article <502@seer.UUCP> bll@seer.UUCP (Brad Lanam) writes:
|>
|>    Is there some easy way to get a function key using Berkeley curses?
|>I don't have access to the documentation, and the O'Reilly "curses" book
|>doesn't mention anything about the special keys.
|
|Use the keypad(win,bf) function.
|
|For example, I always do:	keypad(stdscr,1);
|to turn on keypad mode.
|
|Then, you can use the getch() function to read the keys in.  Look
|at your system's curses.h file for the key definitions.  Mine has
|a lot of comments explaining what they are.
|
|Oh, you may want to call cbreak() to get into one-key-at-a-time
|mode.

Sorry to correct you Greg, but as far as I know BSD curses (which is
where the question was about) doesn't have keypad(); it is a AT&T-ism.

So in the Berkeley variant you will have to roll your own; this is not too
hard, and I'll try to sketch it out globally:

a) For each terminal capability that represents a function key - globally
speaking the k... capabilities - fetch that capability. See the manual page
for termcap(3) (functions like tgetent, tgetstr etc.).

b) You will have to do some translation of possibile capabilities to
keycodes returned, e.g. if kup (cursor up) was pressed, you want to
return KEY_UP (which will be a unique code in your header file, that
you include wherever you include curses.h; following the AT&T example
you could reserve codes above 0x100 for function keys, so that the
lower codes can be used for ordinary ASCII characters). This could
be implemented by an array of structs containing a capability name
and a keycode.

c) Instead of using (w)getch, create your own function that calls
(w)getch to get characters. You will probably want to set cbreak() and
noecho(). Now, as long as characters recieved through (w)getch form
a prefix to one or more function key sequences, store them in a buffer.
As soon as you get
    1) exactly one match   -->  return the corresponding keycode
    2) no more matches     -->  return each character in the buffer separately
                               (using a static buffer, and index).
    3) time out            -->  like 2).

3) (setting up an alarm & signal) is needed for instance if you want to
process a single escape key; you must be able to tell apart a single
esc sequence, e.g. "\33[D", from the three separate characters (though
I agree with whoever says that using both escape sequences and an esc
key is asking for trouble; you can't do it consistently).

Cheers,
         Leo.

greg@gagme.chi.il.us (Gregory Gulik) (07/06/90)

In article <816@ehviea.ine.philips.nl> leo@ehviea.UUCP (Leo de Wit) writes:
>
>Sorry to correct you Greg, but as far as I know BSD curses (which is
>where the question was about) doesn't have keypad(); it is a AT&T-ism.


If you say so.

I have used mostly System V, and my BSD exprience included systems
that seemed to support the keypad() function just fine.



-greg


-- 
Gregory A. Gulik					Call Gagme, a public
	greg@gagme.chi.il.us  ||  ...!gagme!greg	access UNIX system at
	||  gulik@depaul.edu				(708) 318-7133

guy@auspex.auspex.com (Guy Harris) (07/08/90)

>>Sorry to correct you Greg, but as far as I know BSD curses (which is
>>where the question was about) doesn't have keypad(); it is a AT&T-ism.
>
>If you say so.

I say so too.

>I have used mostly System V, and my BSD exprience included systems
>that seemed to support the keypad() function just fine.

Well, on SunOS 4.0.3:

	#
	# Let's see if it's a macro in the BSD-environment "curses":
	#
	auspex% egrep keypad /usr/include/curses.h

	#
	# Well, I guess it's not.  Let's see if it's a library routine:
	#
	auspex% nm /usr/lib/libcurses.a | egrep keypad

	#
	# Nope, it's not a library routine, either.  Just for laughs,
	# let's see if it's a library routine in the S5-environment
	# "curses":
	#
	auspex% nm /usr/5lib/libcurses.a | egrep keypad
	keypad.o:
	00000000 T _keypad

	#
	# Sure is.  Let's take a look at the source from the 4.3BSD
	# tape, just for laughs:
	#
	auspex% pushd /home/unix_src/bsd4.3/usr.lib/libcurses
	/home/unix_src/bsd4.3/usr.lib/libcurses ~
	auspex% egrep keypad *
	egrep: Read error on profiled: Is a directory

	#
	# Nope - if the "curses" you tried really was a BSD-environment
	# curses, your vendor must have added it.
	#