[comp.lang.c] Using arrow keys with curses.

mouse@mcgill-vision.UUCP (der Mouse) (06/13/88)

In article <485@cieunix.rpi.edu>, curt@cieunix.rpi.edu (Curt Signorino) writes:
> I've also been trying to access the arrow keys with curses, but
> haven't quite got the hang of it.  What I'd had in mind was doing a
> getchar() and then switching on the appropriate value of the arrow
> key to the cursor moving routines.

Arrow keys generally send multi-character sequences; doing just one
getchar() will get just one character.  You'd need to look up the
sequences the arrow keys send somewhere (termcap has capabilities for
this: kl, kr, kd, ku).  Then if they are more than one character long,
you will need to call getchar() multiple times and parse the results
somehow.  It's not simple.

> I could use something like 'hjkl' as my cursor moving keys, but I
> wanted to be able to write to the screen as the default.  If I used
> 'hjkl' I'd need a special "write" key to signal that I wanted to
> write on that spot.

This sounds like a primitive flavor of text editor.  You might consider
looking at how existing editors do this.  Vi, for example, does what
you mention in that paragraph: depend on being in one or another of a
set of "modes" to tell what a given key (h, for example) does.  Emacs
uses (usually fixed) control characters, like ^B for moving left one
character.  Other editors (I'm not familiar with any others) may have
other conventions.  Some editors doubtless go to the trouble to read
multi-character key sequences and do the appropriate thing; I believe
both vi and emacs can be set up to do this sort of thing.

You pays your money and you takes your choice, sort of.  You can opt
for one of the simple solutions: simple to implement, somewhat rougher
to use.  Or you can go for something more complex: more work for the
programmer but less pain for the user.  It's a design tradeoff; look at
what it'll be used for and such and take your pick.

					der Mouse

			uucp: mouse@mcgill-vision.uucp
			arpa: mouse@larry.mcrcim.mcgill.edu

larry@jc3b21.UUCP (Lawrence F. Strickland) (06/14/88)

From article <1162@mcgill-vision.UUCP>, by mouse@mcgill-vision.UUCP (der Mouse):
> In article <485@cieunix.rpi.edu>, curt@cieunix.rpi.edu (Curt Signorino) writes:
>> I've also been trying to access the arrow keys with curses, but
>> haven't quite got the hang of it.  What I'd had in mind was doing a
> 
> Arrow keys generally send multi-character sequences; doing just one
> getchar() will get just one character.  You'd need to look up the

Of course, it goes without saying that if you are using System V.2.0.4 or
later, curses comes with a routine (wgetch) that picks up these as
'extended' key codes (KEY_UP, etc).  However, if you use BSD 4.2 routines
or if you use XENIX (SCO style) or other earlier systems, this doesn't
work.

I use most of the above at one time or another during the day, so I came up
with a set of functions (getkeys and wgetch) that could be linked with your
program to simulate the latter curses.  It uses the same key definitions so
that it is compatible with curses and works with the various versions of
SCO XENIX as well (these were the HARDEST to get to work!)

Unfortunately, the algorithm I use is somewhat slow and with slower
processors (notably the AT&T 3b2/300) it is prone to lose characters
occasionally.  In my defense, so is vi in the same circumstances.  On
faster processors, I've had little trouble.

The same routine(s) were installed in Micro-EMACS 3.9e to make a version
that works with curses/termcap/terminfo instead of against it so that
cursor control and function control keys will work under UNIX.

If anyone is interested, I could probably post the routines to
comp.sources.misc or alt.sources or whatever.  Please let me know.  They
are fairly short.

-l
-- 
+--------------------------------------+-- St. Petersburg Junior College --+
|        Lawrence F. Strickland        |   P.O. Box 13489                  |
| ...gatech!codas!usfvax2!jc3b21!larry |   St. Petersburg, FL 33733        |
+-(or) ...gatech!usfvax2!jc3b21!larry -+-- Phone: +1 813 341 4705 ---------+

dcon@ihlpe.ATT.COM (452is-Connet) (06/15/88)

In article <412@jc3b21.UUCP> larry@jc3b21.UUCP (Lawrence F. Strickland) writes:
>Of course, it goes without saying that if you are using System V.2.0.4 or
>later, curses comes with a routine (wgetch) that picks up these as
>'extended' key codes (KEY_UP, etc).

Provided, of course, that you enable the keypad with
'keypad(window,TRUE);'  where window will "normally" be stdscr.

Dave Connet
ihnp4!ihlpe!dcon

greg@xios.XIOS.UUCP (Greg Franks) (06/16/88)

In article <1162@mcgill-vision.UUCP> mouse@mcgill-vision.UUCP (der Mouse) writes:
>In article <485@cieunix.rpi.edu>, curt@cieunix.rpi.edu (Curt Signorino) writes:
>> I've also been trying to access the arrow keys with curses, but
>> haven't quite got the hang of it.  What I'd had in mind was doing a
>> getchar() and then switching on the appropriate value of the arrow
>> key to the cursor moving routines.
>
>Arrow keys generally send multi-character sequences; doing just one
>getchar() will get just one character.  You'd need to look up the
>sequences the arrow keys send somewhere (termcap has capabilities for
>this: kl, kr, kd, ku).  Then if they are more than one character long,
>you will need to call getchar() multiple times and parse the results
>somehow.  It's not simple.
>

I don't know whether the original author stated which version of UNIX he
was on....

Sys V curses handles the arrow (and other function keys) automagically. 
Here are some code segments...

		initscr();		/* read terminfo database 	*/
		cbreak();		/* Cbreak mode.			*/
		noecho();		/* Don't echo chars		*/
		keypad( stdscr, 1 );	/* But do allow keypad ops	*/
		typeahead( 0 );		/* Allow typeahead.		*/

...
		int c;			/* NOT char!!!! */

		c = wgetch( stdscr );

		switch( c ) {

		case KEY_RIGHT: case 'L': case 'l':
		case KEY_DOWN:	case 'J': case 'j':
			cursor = curr_menu[cursor].next;
			break;

		case KEY_LEFT:	case 'H': case 'h':
		case KEY_UP:	case 'K': case 'k':
			cursor = curr_menu[cursor].prev;
			break;


**IMPORTANT** Don't use getc() or friends.  Use the curses equivalent. 
I don't know if this stuff is in Berkeley.

Good luck!
-- 
Greg Franks                   XIOS Systems Corporation, 1600 Carling Avenue,
utzoo!dciem!nrcaer!xios!greg  Ottawa, Ontario, Canada, K1Z 8R8. (613)725-5411.
   ACME Electric: When you can't find your shorts, call us!