[comp.sys.amiga.tech] Character I/O from the 'CON:'sole

Radagast@cup.portal.com (sullivan - segall) (08/06/90)

Does anyone know how to get immediate keyboard events from the 
default console?  (I.e: The one that is attached to the CLI.) 
I've tried finding it in the system lists (unsuccessfully) and
I've tried setting the raw keyboard events Ansi command:

	puts("\x9b" "1{");

The latter seems to lock to the program up permanently.  It
becomes impossible to get a linefeed because the return key
has been converted into an escape sequence, and getchar() seems
to want a complete line before continuing.

I need an example that will allow me to react to keyboard input
the way the Commodore supplied "more" command does.

I asked once before and got no replies, so I hit the books and I'm
still stumped.  I'd really appreciate the help, or any indication
of the right place to look.

                           -Sullivan_-_Segallc(a.k.a. Radagast)
_______________________________________________________________
 
/V\ "I regret to say that we of the FBI are powerless to act in
 '   cases of oral-genital intimacy,  unless it has in some way
obstructed interstate commerce." -- J. Edgar Hoover
_______________________________________________________________
 
Mail to: ...sun!portal!cup.portal.com!radagast or
         radagast@cup.portal.com
 

markv@kuhub.cc.ukans.edu (08/06/90)

In article <32495@cup.portal.com>, Radagast@cup.portal.com (sullivan - segall) writes:
> Does anyone know how to get immediate keyboard events from the 
> default console?  (I.e: The one that is attached to the CLI.) 

Yes.

> I've tried finding it in the system lists (unsuccessfully) and
> I've tried setting the raw keyboard events Ansi command:

First you need to find *your* consoles device handler.  You use
DevProc() to do this.  DevProc() takes a string as an argument,
(device name) and returns it's process pointer.  In the case of your
console window you DONT do DevProc("CON:") because there will be
several CON:s and you will most likely NOT get yours.  Use 
DevProc("*") which returns your stdin/out handler which is a CON: or
NEWCON: if things havn't been redirected.
 
> 	puts("\x9b" "1{"); 
> The latter seems to lock to the program up permanently.  It
> becomes impossible to get a linefeed because the return key
> has been converted into an escape sequence, and getchar() seems
> to want a complete line before continuing.

Your problem is getting normal (cooked) ASCII codes, but
console.device buffers input to a new line.  If you put it in RAW:
mode then you get other problems. 

> I need an example that will allow me to react to keyboard input
> the way the Commodore supplied "more" command does.

You need to Send an AmigaDOS "packet" to your console's device handler
process.  A packet is an Exec Message with a pointer to a command
and N arguments.

With 1.2 there is a new packet type that is something like SETRAWMODE
which turns off line buffering (it is different than making it RAW:).
The 1.2 AmigaDOS manual has the packet buried in the text under a "new
for 1.2 note".  Also the packet IDs and a structure definition for a
StdPacket message which is a Message with the packet tacked on the
end can be found in dosextens.h.

Arp has a function SendPacket() that can greatly simplify the code.

> I asked once before and got no replies, so I hit the books and I'm
> still stumped.  I'd really appreciate the help, or any indication
> of the right place to look.
> 
>                            -Sullivan_-_Segallc(a.k.a. Radagast)

-- 
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Mark Gooderum			Only...		\    Good Cheer !!!
Academic Computing Services	       ///	  \___________________________
University of Kansas		     ///  /|         __    _
Bix:	  markgood	      \\\  ///  /__| |\/| | | _   /_\  makes it
Bitnet:   MARKV@UKANVAX		\/\/  /    | |  | | |__| /   \ possible...
Internet: markv@kuhub.cc.ukans.edu
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

dillon@overload.Berkeley.CA.US (Matthew Dillon) (08/07/90)

In article <32495@cup.portal.com> Radagast@cup.portal.com (sullivan - segall) writes:
>Does anyone know how to get immediate keyboard events from the
>default console?  (I.e: The one that is attached to the CLI.)
>I've tried finding it in the system lists (unsuccessfully) and
>I've tried setting the raw keyboard events Ansi command:
>
>	puts("\x9b" "1{");
>
>The latter seems to lock to the program up permanently.  It
>becomes impossible to get a linefeed because the return key
>has been converted into an escape sequence, and getchar() seems
>to want a complete line before continuing.
>
>I need an example that will allow me to react to keyboard input
>the way the Commodore supplied "more" command does.

    Under Aztec C there is an ioctl() that will put the console into
    RAW mode.  Under Lattice C I believe there is a function call but
    do not remember what it is.  Under DICE you can:

	    setvbuf(stdin, NULL, _IONBF, 0);

    This is the standard ANSI way of doing it, but I'm not sure if the
    latter call will work under Lattice or Aztec.  The following code will
    also accomplish the function, but you have to modify it appropriately
    to retrieve the AmigaDOS file handle from stdin depending on the
    compiler:

    NOTE: This code is provided As-Is and probably needs to be modified to
    work with other compilers.

int
set_console_raw(fd, rawmode)
int fd;
short rawmode;
{
    MsgPort *mp;
    BPTR fh;
    long Arg[1], res;

    fh = (BPTR)fdtofh(fd);      /*  DICE, have to find it some other way */
				/*  for Lattice, Aztec			 */
    if (fh == NULL)
	return(-1);
    if (IsInteractive(fh) == 0) {
	errno = ENOTTY;
	return(-1);
    }
    mp = ((struct FileHandle *)(BADDR(fh)))->fh_Type;
    if (rawmode)
	Arg[0] = -1L;
    else
	Arg[0] = 0L;
    res = SendPacket(mp, ACTION_SCREEN_MODE, Arg, 1);   /* Put it in RAW: mode */
    if (res == 0) {
	errno = ENXIO;
	return (-1);
    }
    return (0);
}

/*
 * Function - SendPacket written by Phil Lindsay, Carolyn Scheppner, and Andy
 * Finkel. This function will send a packet of the given type to the Message
 * Port supplied.
 */

typedef struct StandardPacket StandardPacket;

long
SendPacket(pid, action, args, nargs)
MsgPort *pid;	/* process indentifier ... (handler's message port )    */
long action;	/* packet type ... (what you want handler to do )       */
long args[];	/* a pointer to an argument list    */
long nargs;	/* number of arguments in list	    */
{
    MsgPort *replyport;
    StandardPacket *packet;
    long count, *pargs, res1;

    replyport = CreatePort(NULL, 0L);
    if (!replyport)
	return(0);

    /* Allocate space for a packet, make it public and clear it */

    packet = AllocMem(sizeof(StandardPacket), MEMF_PUBLIC | MEMF_CLEAR);
    if (!packet) {
	DeletePort(replyport);
	return(0);
    }
    packet->sp_Msg.mn_Node.ln_Name = (char *) &(packet->sp_Pkt);
    packet->sp_Pkt.dp_Link = &(packet->sp_Msg);
    packet->sp_Pkt.dp_Port = replyport;
    packet->sp_Pkt.dp_Type = action;

    /* copy the args into the packet */

    pargs = &(packet->sp_Pkt.dp_Arg1);      /* address of first argument */
    for (count = 0; count < nargs; count++)
	pargs[count] = args[count];

    PutMsg(pid, packet);    /* send packet */

    WaitPort(replyport);
    GetMsg(replyport);

    res1 = packet->sp_Pkt.dp_Res1;

    FreeMem(packet, sizeof(StandardPacket));
    DeletePort(replyport);

    return (res1);
}


>Mail to: ...sun!portal!cup.portal.com!radagast or
>	  radagast@cup.portal.com
>

			    -Matt

--


    Matthew Dillon	    dillon@Overload.Berkeley.CA.US
    891 Regal Rd.	    uunet.uu.net!overload!dillon
    Berkeley, Ca. 94708
    USA