/*
* S A S C
*
* Some conio replacements for the Amiga, using SAS/C
*
* Written by M. Stapleton of Graphic Bits
*
* Oct 20 1996
*
* This code is hereby donated to the Public Domain.
*/
#include <exec/types.h>
#include <exec/memory.h>
#include <exec/ports.h>
#include <proto/exec.h>
#include <proto/dos.h>
#include <stdlib.h>
#include <ctype.h>
#include <stdio.h>
#include <ios1.h>
#include "keys.h"
int coninit(void);
void confin(void);
int akbhit(void);
int agetch(void);
int agetche(void);
int agetchr(void);
/* Private prototypes */
struct MsgPort *findconport(void);
struct StandardPacket *createpkt(void);
void deletepkt(struct StandardPacket **packet);
void fillpkt(struct StandardPacket *packet, LONG action, LONG args[], LONG nargs);
void sendpkt(struct StandardPacket *packet, struct MsgPort *port, struct MsgPort *replyport);
void setmode(int mode);
static int initflag; /* Set to 1 after console is set to raw mode */
static struct StandardPacket *conpacket;
static struct MsgPort *conreply;
static struct MsgPort *conport;
static BPTR conin; /* Console input AmigaDOS file handle */
/* Initialize console stuff */
int coninit(void)
{
if (initflag)
{
return 0;
}
/* Find console filehandle & message port */
conport = findconport();
if (conport == NULL)
{
return 0;;
}
conpacket = createpkt();
if (conpacket == NULL)
{
return 0;;
}
conreply = (struct MsgPort *) CreatePort(NULL, 0);
if (conreply == NULL)
{
confin();
return 0;
}
setmode(-1); /* Set RAW Console input */
initflag = 1;
return 1;
}
/* End console stuff */
void confin(void)
{
if (conreply)
{
if (initflag)
{
conport = findconport();
if (conport != NULL)
{
setmode(0);
}
}
initflag = 0;
DeletePort(conreply);
}
if (conpacket)
{
deletepkt(&conpacket);
}
}
/*
* Find console filehandle & message port
* Returns message port & sets conin
*/
struct MsgPort *findconport(void)
{
struct UFB *ufb;
ufb = chkufb(0);
if (ufb == NULL)
{
return NULL;
}
conin = ufb->ufbfh);
if (conin == NULL)
{
return NULL;
}
return ((struct FileHandle *) (conin << 2))->fh_Type;
}
struct StandardPacket *createpkt(void)
{
struct StandardPacket *packet;
packet = (struct StandardPacket *)AllocMem((long) sizeof(struct StandardPacket), MEMF_PUBLIC | MEMF_CLEAR);
if (packet == NULL)
{
return NULL;
}
packet->sp_Msg.mn_Node.ln_Name = (char *) &(packet->sp_Pkt);
packet->sp_Pkt.dp_Link = &(packet->sp_Msg);
return packet;
}
void deletepkt(struct StandardPacket **packet)
{
if (*packet)
{
FreeMem((char *) *packet, (long) sizeof(struct StandardPacket));
}
*packet = NULL; /* So we can't delete twice */
}
void fillpkt(struct StandardPacket *packet, LONG action, LONG args[], LONG nargs)
{
LONG *pargs;
packet->sp_Pkt.dp_Type = action;
/* copy the arguments into the packet */
pargs = &(packet->sp_Pkt.dp_Arg1); /* address of 1st arg */
while (nargs--)
{
*pargs++ = *args++;
}
}
void sendpkt(struct StandardPacket *packet, struct MsgPort *port, struct MsgPort *replyport)
{
packet->sp_Pkt.dp_Port = replyport;
PutMsg(port, (struct Message *) packet);
}
/*
* Set console mode: -1 -> raw; 0 -> cooked.
*/
void setmode(int mode)
{
fillpkt(conpacket, ACTION_SCREEN_MODE, (LONG *) &mode, 1);
sendpkt(conpacket, conport, conreply);
WaitPort(conreply);
GetMsg(conreply);
}
/*
#define TIMEOUT 1 * Number of microseconds to wait. Don't use 0, due to
* a bug in the V1 "timer.device".
*/
/*
* Tests if a character is available to be read from the console.
* Returns 1 if there is, 0 if there isn't, and -1 on failure.
* Assumes the console is set to "raw" mode.
*/
int akbhit(void)
{
struct UFB *ufb;
ufb = chkufb(0);
if (ufb == NULL || ufb->ufbfh == NULL)
{
return -1;
}
return WaitForChar(ufb->ufbfh, TIMEOUT) ? 1 : 0;
}
/*
* Get a character from the console without waiting for <RETURN>.
* Returns EOF on end-of-file or failure.
* Assumes the console is set to "raw" mode.
*/
int agetch()
{
int len;
unsigned char buf;
struct UFB *ufb;
ufb = chkufb(0);
if (ufb == NULL || ufb->ufbfh == NULL)
{
return EOF;
}
len = Read(ufb->ufbfh, &buf, 1);
if (len == 0)
{
return EOF;
}
return (int) buf;
}
/* Getch() with echo */
int agetche(void)
{
int buf;
buf = agetch();
if (buf != EOF)
{
Write(conin, (char *) &buf, 1); /* Well... :) */
}
return buf;
}
/* Handle function & cursor keys, etc. Needs work! */
int agetchr(void)
{
int c, d;
c = agetch();
if (c == 0x9b && akbhit())
{
/* Special key report sequence */
d = 0;
do
{
c = agetch();
if (c == EOF || c == '~')
{
break;
}
if (isdigit(c))
{
c -= '0';
}
d = 10 * d + c;
}
while (c < '@' && akbhit());
c = 256 + d;
}
/* Convert keys - should be done with table(s) */
if (c > 0x80)
{
switch (c)
{
/* Convert Ctrl-Alt letters to Alt */
case 0x0081:
c = Key_A_A;
break;
case 0x0082:
c = Key_A_B;
break;
case 0x0083:
c = Key_A_C;
break;
case 0x0084:
c = Key_A_D;
break;
case 0x0085:
c = Key_A_E;
break;
case 0x0086:
c = Key_A_F;
break;
case 0x0087:
c = Key_A_G;
break;
case 0x0088:
c = Key_A_H;
break;
case 0x0089:
c = Key_A_I;
break;
case 0x008A:
c = Key_A_J;
break;
case 0x008B:
c = Key_A_K;
break;
case 0x008C:
c = Key_A_L;
break;
case 0x008D:
c = Key_A_M;
break;
case 0x008E:
c = Key_A_N;
break;
case 0x008F:
c = Key_A_O;
break;
case 0x0090:
c = Key_A_P;
break;
case 0x0091:
c = Key_A_Q;
break;
case 0x0092:
c = Key_A_R;
break;
case 0x0093:
c = Key_A_S;
break;
case 0x0094:
c = Key_A_T;
break;
case 0x0095:
c = Key_A_U;
break;
case 0x0096:
c = Key_A_V;
break;
case 0x0097:
c = Key_A_W;
break;
case 0x0098:
c = Key_A_X;
break;
case 0x0099:
c = Key_A_Y;
break;
case 0x009A:
c = Key_A_Z;
break;
/* Alt Numeric keys */
case 0x00b9:
c = Key_A_1;
break;
case 0x00b2:
c = Key_A_2;
break;
case 0x00b3:
c = Key_A_3;
break;
case 0x00a2:
c = Key_A_4;
break;
case 0x00bc:
c = Key_A_5;
break;
case 0x00bd:
c = Key_A_6;
break;
case 0x00be:
c = Key_A_7;
break;
case 0x00b7:
c = Key_A_8;
break;
case 0x00ab:
c = Key_A_9;
break;
case 0x00bb:
c = Key_A_0;
break;
/* Plain Function keys */
case 0x0100:
c = Key_F1;
break;
case 0x0101:
c = Key_F2;
break;
case 0x0102:
c = Key_F3;
break;
case 0x0103:
c = Key_F4;
break;
case 0x0104:
c = Key_F5;
break;
case 0x0105:
c = Key_F6;
break;
case 0x0106:
c = Key_F7;
break;
case 0x0107:
c = Key_F8;
break;
case 0x0108:
c = Key_F9;
break;
case 0x0109:
c = Key_F10;
break;
/* Shifted Function keys */
case 0x010a:
c = Key_S_F1;
break;
case 0x010b:
c = Key_S_F2;
break;
case 0x010c:
c = Key_S_F3;
break;
case 0x010d:
c = Key_S_F4;
break;
case 0x010e:
c = Key_S_F5;
break;
case 0x010f:
c = Key_S_F6;
break;
case 0x0110:
c = Key_S_F7;
break;
case 0x0111:
c = Key_S_F8;
break;
case 0x0112:
c = Key_S_F9;
break;
case 0x0113:
c = Key_S_F10;
break;
/* Help -> Alt-h */
case 0x013f:
c = Key_A_H;
break;
/* Cursor keys */
case 0x0141:
c = Key_Up;
break;
case 0x0142:
c = Key_Dwn;
break;
case 0x0143:
c = Key_Rgt;
break;
case 0x0144:
c = Key_Lft;
break;
/* Shift-Cursor keys */
case 0x0153:
c = Key_PgDn;
break;
case 0x0154:
c = Key_PgUp;
break;
case 0x0280:
c = Key_C_Rgt;
break;
case 0x0281:
c = Key_C_Lft;
break;
default:
break;
}
}
return c;
}
syntax highlighted by Code2HTML, v. 0.9.1