/* * 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 #include #include #include #include #include #include #include #include #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 . * 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; }