/* 
 *	raw.c - for Amigas
 *
 *    This is a routine for setting a given stream to raw or cooked mode.
 * This is useful when you are using Lattice C to produce programs that
 * want to read single characters with the "getch()" or "fgetc" call.
 *
 * Written : 18-Jun-87 By Chuck McManis. 
 * 	     If you use it I would appreciate credit for it somewhere.
 *
 * I remangled this to compile with gcc and 2.0 header files 
 * and to only work with the console.  I incorporated stuff I learned
 * from ConPackets.c by C. Scheppner, A. Finkel, P. Lindsay  CBM
 * - Roger Ang, May 1995
 */

#include <exec/types.h>
#include <libraries/dos.h>
#include <libraries/dosextens.h>
#include <stdio.h>
/* for 1.3
#include <ios1.h>
#include <error.h> */

#include <errno.h>

/* New Packet in 1.2 
#define ACTION_SCREEN_MODE	994L */

extern	int	errno;		/* The error variable */

long raw(void);
long cooked(void);

/* from AK_con.c */
extern LONG sendpkt();

/* fiddling with low level IO flags */
static short orig_flags;

/*
 * Function raw() - Convert the specified file pointer to 'raw' mode. This
 * only works on TTY's and essentially keeps DOS from translating keys for
 * you, also (BIG WIN) it means getch() will return immediately rather than
 * wait for a return. You lose editing features though.
 */
long
raw()
{
  long			Arg[1],res1;
  struct InfoData       *id;
  struct MsgPort        *con_mp;
  struct Process        *me;

  /* Get original buffering of stdout and set to unbuffered.  
     Need to do this because ALL console I/O is set to raw   
     Buffered I/O won't be displayed 'til EOL is encountered.
     Note: the flags are compiler dependent, and are defined
     in stdio.h */

#if LATTICE
  orig_flags = stdout->_flag;
  stdout->_flag = stdout->_flag | _IONBF;
#else
  orig_flags = stdout->_flags;
  stdout->_flags = stdout->_flags | __SNBF;
#endif

  /* Alloc to insure longword alignment */
  id = (struct InfoData *)AllocMem(sizeof(struct InfoData),
                                   MEMF_PUBLIC|MEMF_CLEAR);
  if (!id) return(0);

  /* get console of current active task */
  me = (struct Process *) FindTask(NULL);
  con_mp = (struct MsgPort *) me->pr_ConsoleTask;
      
  Arg[0] = -1L;
  res1 = (LONG)sendpkt(con_mp,ACTION_SCREEN_MODE,Arg,1); /* Put it in RAW: mode */
  FreeMem(id,sizeof(struct InfoData));

  if (res1 == 0) {
    errno = ENXIO;
    return(-1);
  }
  return(0);
}

/*
 * Function - cooked() this function returns the designate file pointer to
 * it's normal, wait for a <CR> mode. This is exactly like raw() except that
 * it sends a 0 to the console to make it back into a CON: from a RAW:
 */
long
cooked()
{
  long			Arg[1],res1;
  struct InfoData       *id;
  struct MsgPort        *con_mp;
  struct Process        *me;

  /* set stdout to original mode */
#if LATTICE
  stdout->_flag = orig_flags;
#else
  stdout->_flags = orig_flags;
#endif 

  /* Alloc to insure longword alignment */
  id = (struct InfoData *)AllocMem(sizeof(struct InfoData),
                                   MEMF_PUBLIC|MEMF_CLEAR);
  if (!id) return(0);

  /* get console of current active task */
  me = (struct Process *) FindTask(NULL);
  con_mp = (struct MsgPort *) me->pr_ConsoleTask;

  Arg[0] = 0;
  res1 = (LONG)sendpkt(con_mp,ACTION_SCREEN_MODE,Arg,1);
  FreeMem(id,sizeof(struct InfoData));

  if (res1 == 0) {
    errno = ENXIO;
    return(-1);
  }
  return(0);
}
