(c)  Copyright 1989 Commodore-Amiga, Inc.   All rights reserved.
The information contained herein is subject to change without notice, and 
is provided "as is" without warranty of any kind, either expressed or implied.  
The entire risk as to the use of this information is assumed by the user.



                     CON: and Raw Event Streams

                      Carolyn Scheppner - CATS


     The ability to toggle CON: or NEWCON: windows in and out of
RAW: mode can provide some convenient features for Amiga programmers.
Normally, CON: and NEWCON: windows like the CLI provide a simple, 
buffered form of console input where all echoing and line editing is 
handled for you and you receive the characters when the user hits 
the RETURN key.  But sometimes you need more control, or more keys, 
or more information than CON: provides.
 
     The AmigaDOS ACTION_SCREEN_MODE packet allows you to toggle
a CON: or NEWCON: window into RAW: mode.  In RAW: mode, you still
get keymap character translation for international compatibility,
but you get each ASCII character as it is received instead of when
the user hits the Return key.  In RAW: mode, you also receive the 
keymap's escape strings for keys such as the cursor and function keys.  
However, since you receive all characters directly, you are responsible 
for managing all filtering, echoing and line editing.

     The ability to toggle a window back and forth between CON: and RAW: 
gives you the ability to match the input style to your program's needs.  
For example, the More program on Workbench keeps its CON: text display 
window in RAW: mode most of the time for immediate processing of single-key 
user commands.  But when the user selects a key command which requires a 
string argument to be input (such as the "/" or "." search commands), the 
More program temporarily toggles the window back into CON: mode to let 
the system provide automatically filtered and echoed line input.


     In addition to providing immediate character input and escape strings 
for the non-vanilla keys, RAW: windows may be set up to pass on a variety 
of raw events as escape strings.  These events are requested with the 
aSRE (SET RAW EVENTS) escape sequence.  This sequence and its counterpart 
(RESET RAW EVENTS) have the following form:

aSRE   SET RAW EVENTS          <CSI>n{
aRRE   RESET RAW EVENTS        <CSI>n}

<CSI> is the Control Sequence Introducer and n is the number in ASCII of the 
raw event you wish to receive.  The Control Sequence Introducer may be either 
the two-byte code "\033[" (also known as ESC[ ) or the one-byte code "\233"
(ESC with the high bit set ).  A full list of the types of raw events available 
may be found in the Console Input and Output chapter of the Bantam AmigaDOS 
manual.  This list includes:

     3  Window made active
     9  Requester activity
    12  Window resized
    15  Disk removed
    16  Disk inserted

   For example, Window Active events would be requested by writing
the escape string "\033[3{" to the raw mode CON:, and turned off
by writing "\033[3}".

   The example program DiskI.c toggles the CLI window into RAW: mode
and asks for DISKINSERTED and DISKREMOVED events.  Note that the
two requests are combined into a single escape sequence by separating
the ASCII event numbers with a semicolon.  Both events 15 and 16
are requested using the escape string "\033[15;16{".

    DiskI.c demonstrates several techniques which you may want to try
in your programs:

      - Sending an AmigaDOS packet
      - Toggling a CON: into RAW mode and back
      - Requesting, receiving, and resetting additional raw events






/*
  Diski.c - Get Disk Inserted and Removed Raw Events from CLI window
  Carolyn Scheppner  CBM  04/89

  Copyright (c) 1989 Commodore-Amiga, Inc.
 
  Executables based on this information may be used in software
  for Commodore Amiga computers.  All other rights reserved.
 
  This information is provided "as is"; no warranties are made.
  All use is at your own risk, and no liability or responsibility is assumed.
*/

#include "exec/types.h"
#include "exec/memory.h"
#include "libraries/dos.h"
#include "libraries/dosextens.h"

/* Defined in 1.3 Includes
#define  DOSTRUE (-1L)
#define  DOSFALSE (0L)
*/


main()
   {
   printf("\nThis demo will set CON to RAW, request DISKINSERTED and\n");
   printf("DISKREMOVED events, then prompt for disk insertion/removal\n");
   printf("in any drive.\n\n");
   printf("Experiment by inserting and removing disks, and typing keys.\n");
   printf("The program will print out all input characters in ascii,\n");
   printf("but will print escape (1B) as ESC, and csi (9B) as CSI.\n");
   printf("[ Press CTRL/C to exit when done experimenting. ]\n\n");

   /* Set our process's pr_ConsoleTask to RAW */
   setRawCon(DOSTRUE);

   /* Ask RAW window for raw DISKINSERTED and DISKREMOVED events */
   printf("\033[15;16{");

   printf("Please insert or remove disk in any drive...\n\n");

   while(!(SetSignal(0,0)&SIGBREAKF_CTRL_C))
      {
      dochar();
      }

   /* Clear the CTRL/C signal */
   SetSignal(0,SIGBREAKF_CTRL_C);

   /* Tell RAW window to stop sending raw DISKINSERTED/REMOVED events */
   printf("\033[15;16}");

   printf("\n\nDemo has now asked to NOT receive DISK events.\n");
   printf("Inserting a disk now should cause no input characters.\n");
   printf("[ Press CTRL/C to exit when done experimenting. ]\n\n");

   while(!(SetSignal(0,0)&SIGBREAKF_CTRL_C))
      {
      dochar();
      }

   /* Reset to normal CON */
   setRawCon(DOSFALSE);

   printf("\nDone.  Console has been reset to CON:, demo exiting...\n\n");
   }


dochar()
   {
   UBYTE c;

   c=getchar();

   if(c==0x1B)        printf("\nESC\n");
   else if(c==0x9B)   printf("\nCSI\n");
   else               putchar(c);
   }


/* sendpkt code - A. Finkel, P. Lindsay, C. Scheppner  CBM */

LONG setRawCon(toggle)
LONG toggle;     /* DOSTRUE (-1L)  or  DOSFALSE (0L) */
   {
   struct MsgPort *conid;
   struct Process *me;
   LONG myargs[8] ,nargs, res1;

   me = (struct Process *) FindTask(NULL);
   conid = (struct MsgPort *) me->pr_ConsoleTask;

   myargs[0]=toggle;
   nargs = 1;
   res1 = (LONG)sendpkt(conid,ACTION_SCREEN_MODE,myargs,nargs);
   return(res1);
   }


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

   if(!pid) return(NULL);
   replyport = (struct MsgPort *) CreatePort(NULL,0);
   if(!replyport) return(NULL);

   packet = (struct StandardPacket *) 
      AllocMem((long)sizeof(struct StandardPacket),MEMF_PUBLIC|MEMF_CLEAR);
   if(!packet) 
      {
      DeletePort(replyport);
      return(NULL);
      }

   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,(long)sizeof(struct StandardPacket));
   DeletePort(replyport); 

   return(res1);
   }


/* end */


