home *** CD-ROM | disk | FTP | other *** search
-
- /*
- * KEYBOARD.C
- *
- * (C)Copyright 1987 by Matthew Dillon
- *
- * Handle keyboard related stuff such as keyboard mappings. Every time
- * a key is pressed, KEYCTL() is called with the code. KEYCTL() remembers
- * which qualifier keys are currently held down, and when a non-qualifier
- * key is pressed finds the hash entry for the key. If no hash entry
- * exists (e.g. you type a normal 'a') the default keymap is used.
- */
-
- #include "defs.h"
- #include <devices/keymap.h>
- #include <devices/console.h>
-
-
- typedef struct IOStdReq CIO;
-
- #define QUAL_SHIFT 0x01
- #define QUAL_CTRL 0x02
- #define QUAL_AMIGA 0x04
- #define QUAL_ALT 0x08
- #define QUAL_LMB 0x10
- #define QUAL_MMB 0x20
- #define QUAL_RMB 0x40
-
- #define HASHSIZE 64 /* power of 2 */
- #define HASHMASK (HASHSIZE-1)
-
- typedef struct _HASH {
- struct _HASH *next; /* next hash */
- ubyte code; /* keycode */
- ubyte mask; /* qual. mask */
- ubyte qual; /* qual. comp */
- ubyte stat; /* string static? */
- char *str; /* command string */
- } HASH;
-
- HASH *Hash[HASHSIZE];
-
- struct Library *ConsoleDevice;
-
- ubyte ctoa[128];
- ubyte cstoa[128];
-
- void keyctl(struct IntuiMessage *im, int code, unsigned short qual)
- {
- ubyte buf[256];
- ubyte c2;
- short blen = 0;
-
- code &= 0xFF;
- if (im) {
- uword oldQual = im->Qualifier;
-
- im->Qualifier &= ~IEQUALIFIER_REPEAT;
- blen = DeadKeyConvert(im, buf+1, 254, NULL);
- im->Qualifier = oldQual;
- if (blen < 0)
- return;
- }
- c2 = 0;
- if (qual & (IEQUALIFIER_LSHIFT|IEQUALIFIER_RSHIFT))
- c2 |= QUAL_SHIFT;
- if (qual & (IEQUALIFIER_CONTROL))
- c2 |= QUAL_CTRL;
- if (qual & (IEQUALIFIER_LCOMMAND|IEQUALIFIER_RCOMMAND))
- c2 |= QUAL_AMIGA;
- if (qual & (IEQUALIFIER_LALT|IEQUALIFIER_RALT))
- c2 |= QUAL_ALT;
- if ((qual & IEQUALIFIER_CAPSLOCK) && blen == 1 && buf[1] >= 'a' && buf[1] <= 'z')
- c2 |= QUAL_SHIFT;
- if (qual & IEQUALIFIER_LEFTBUTTON)
- c2 |= QUAL_LMB;
- if (qual & IEQUALIFIER_MIDBUTTON)
- c2 |= QUAL_MMB;
- if (qual & (IEQUALIFIER_RBUTTON))
- c2 |= QUAL_RMB;
-
- {
- HASH *hash;
- for (hash = Hash[code&HASHMASK]; hash; hash = hash->next) {
- if (hash->code == code && (c2 & hash->mask) == hash->qual)
- break;
- }
-
- /*
- * Use hash entry only if not in command line mode, or if the
- * entry does not correspond to an alpha key.
- */
-
-
- /* Problem with rawkey-code 0 fixed: Wasn't able to enter `-sign */
- /* was: if (hash) { */
-
- if (hash && code > 0) {
- if (c2 || !Comlinemode || blen > 1 || !ctoa[code]) {
- strcpy(buf, hash->str);
- do_command(buf);
- return;
- }
- }
- }
-
- /*
- * No hash entry
- */
-
- if (blen == 1) {
- buf[0] = '\'';
- buf[2] = 0;
- } else {
- buf[0] = '\`';
- buf[blen+1] = '\'';
- }
- if (blen)
- do_command(buf);
- }
-
- void dealloc_hash(void)
- {
- HASH *hash, *hnext = NULL;
- short i;
-
- for (i = 0; i < HASHSIZE; ++i) {
- for (hash = Hash[i]; hash; hash = hnext) {
- hnext = hash->next;
- if (!hash->stat)
- FreeMem(hash->str, strlen(hash->str)+1);
- FreeMem(hash, sizeof(HASH));
- }
- Hash[i] = NULL;
- }
- }
-
- void resethash(void)
- {
- short i;
- CIO cio;
- static const struct {
- char *from, *to; /* const char *from,*to; */
- } defmap[] = {
- "esc", "esc",
- "c-esc", "recall",
- "return", "split return set oldcol \$(colno)",
- "enter", "firstnb downadd insline set oldcol \$(colno)",
- "up", "up col \$(oldcol) if r (last)",
- "down", "down col \$(oldcol) if r (last)",
- "right", "ifelse r (down first) (right) set oldcol \$(colno)",
- "left", "ifelse l (up last) (left) set oldcol \$(colno)",
- "bs", "ifelse l (up last join2) (bs) set oldcol \$(colno)",
- "del", "ifelse r (join2) (del) set oldcol \$(colno)",
- "tab", "tab",
- "a-up", "upfast col \$(oldcol) if r (last)",
- "a-down", "downfast col \$(oldcol) if r (last)",
- "a-r", "nextr",
- "a-u", "while cl (tlate -32 right)",
- "a-l", "while cu (tlate +32 right)",
- "s-up", "pageup col \$(oldcol) if r (last)",
- "s-down", "pagedown col \$(oldcol) if r (last)",
- "s-right", "wright set oldcol \$(colno)",
- "s-left", "wleft set oldcol \$(colno)",
- "s-tab", "backtab",
- "s-del", "deline",
- "s- ", "( )", /* shift space to space */
- "c-1", "goto block",
- "c-c", "", /* break.. map to a nop */
- "c-l", "wleft",
- "c-r", "wright",
- "c-i", "insertmode on",
- "c-o", "insertmode off",
- "c-j", "join",
- "c-s", "split first down",
- "c-del", "remeol",
- "c-n", "next",
- "c-p", "prev",
- "c-/", "escimm (find )",
- "c-]", "ref",
- "c-[", "ctags",
- "c-g", "escimm (goto )",
- "c-up", "top first set oldcol \$(colno)",
- "c-down", "bottom last set oldcol \$(colno)",
- "c-right", "last set oldcol \$(colno)",
- "c-left", "firstnb set oldcol \$(colno)",
- "c-q", "quit",
- "c-f", "reformat",
- "c-w", "wordwrap toggle",
- "f1", "escimm (insfile )",
- "f2", "escimm (newfile )",
- "f3", "escimm (newwindow newfile )",
- "f6", "saveold iconify",
- "f7", "escimm (bsave )",
- "f8", "saveold escimm (newfile )",
- "f9", "saveold",
- /* "f10", "saveold quit", */
- "c-b", "block",
- "c-u", "unblock",
- "a-d", "bdelete",
- "a-c", "bcopy",
- "a-m", "bmove",
- "a-s", "bsource",
- "a-S", "unblock block block bsource",
- "L-lmb", "tomouse if r (last) set oldcol \$(colno)",
- "L-mmo", "tomouse if r (last) set oldcol \$(colno)",
- "R-rmb", "iconify", /* right button */
- NULL, NULL
- };
-
- dealloc_hash();
- OpenDevice("console.device", -1, (struct IORequest *)&cio, 0);
- ConsoleDevice = (struct Library *)cio.io_Device;
- keyboard_init();
- for (i = 0; defmap[i].from; ++i)
- {
- ubyte code, qual;
- if (get_codequal(defmap[i].from, &code, &qual))
- addhash(code, 1, 0xFF, qual, defmap[i].to);
- }
- }
-
- int returnoveride(int n)
- {
- HASH *hash;
- static ubyte *str;
- static int stat;
-
- for (hash = Hash[0x44&HASHMASK]; hash; hash = hash->next) {
- if (hash->code == 0x44 && hash->qual == 0) {
- if (n) {
- str = (ubyte *)hash->str;
- stat= hash->stat;
- hash->str = "return";
- hash->stat = 1;
- } else {
- if (str == NULL) {
- remhash(0x44, (ubyte)-1, 0);
- } else {
- hash->str = (char *)str;
- hash->stat= stat;
- }
- }
- return(0);
- }
- }
- if (n) {
- addhash(0x44, 1, 0xFF, 0, "return");
- str = NULL;
- }
- }
-
- void addhash(ubyte code, ubyte stat, ubyte mask, ubyte qual, ubyte *str)
- {
- HASH **p, *hash;
-
- hash = *(p = &Hash[code&HASHMASK]);
- while (hash) {
- if (hash->code == code && hash->qual == qual && hash->mask == mask) {
- if (!hash->stat)
- FreeMem(hash->str, strlen(hash->str)+1);
- goto newstr;
- }
- hash = *(p = &hash->next);
- }
- *p = hash = (HASH *)AllocMem(sizeof(HASH), 0);
- hash->next = NULL;
- newstr:
- hash->code = code;
- hash->stat = stat;
- hash->mask = mask;
- hash->qual = qual;
- hash->str = (char *)str;
- if (!stat) /* if not static */
- hash->str = (char *)strcpy((char *)AllocMem(strlen(str)+1, MEMF_PUBLIC), str);
- }
-
-
- remhash(ubyte code, ubyte mask, ubyte qual)
- {
- HASH *hash, **p;
-
- hash = *(p = &Hash[code&HASHMASK]);
- while (hash) {
- if (hash->code == code && hash->qual == qual && hash->mask == mask) {
- if (!hash->stat)
- FreeMem(hash->str, strlen(hash->str)+1);
- *p = hash->next;
- FreeMem(hash, sizeof(HASH));
- return(1);
- }
- hash = *(p = &hash->next);
- }
- return(0);
- }
-
- char *keyspectomacro(char *str)
- {
- HASH *hash;
- ubyte code, qual;
-
- if (get_codequal(str, &code, &qual)) {
- for (hash = Hash[code&HASHMASK]; hash; hash = hash->next) {
- if (hash->code == code) {
- if (hash->qual == (qual & hash->mask)) {
- return(hash->str);
- }
- }
- }
- }
- return(NULL);
- }
-
- void do_map(void)
- {
- ubyte code, qual;
-
- if (get_codequal(av[1], &code, &qual)) {
- addhash(code, 0, 0xFF, qual, av[2]);
- } else {
- title("Unknown Key");
- }
- }
-
- void do_unmap(void) /* key */
- {
- ubyte code, qual;
-
- if (get_codequal(av[1], &code, &qual)) {
- remhash(code, (ubyte)-1, qual);
- } else {
- title("Unknown Command");
- }
- }
-
- void do_clearmap(void)
- {
- resethash();
- }
-
- /*
- * SAVEMAP file
- * SAVESMAP file
- */
-
- void do_savemap(void)
- {
- char sysalso;
- char err = 0;
- char buf[256];
- FILE *fi;
- int i;
- HASH *hash;
- ubyte *ptr;
-
- fi = fopen(av[1], "w");
- if (fi) {
- sysalso = av[0][4] == 's';
- for (i = 0; i < HASHSIZE; ++i) {
- for (hash = Hash[i]; hash; hash = hash->next) {
- if (hash->stat == 0 || sysalso) {
- char soc = '(';
- char eoc = ')';
- char ksoc = '(';
- char keoc = ')';
- short len;
-
- for (ptr = (ubyte *)hash->str; *ptr; ++ptr) {
- if (*ptr == '(')
- break;
- if (*ptr == '\`') {
- soc = '\`';
- eoc = '\'';
- break;
- }
- }
- len = strlen(ptr = cqtoa(hash->code, hash->qual)) - 1;
- if (ptr[len] == '(' || ptr[len] == ')') {
- ksoc = '\`';
- keoc = '\'';
- }
- sprintf(buf, "map %c%s%c %c%s%c\n", ksoc, cqtoa(hash->code, hash->qual), keoc, soc, hash->str, eoc);
- fputs(buf, fi);
- }
- }
- }
- fclose(fi);
- if (err)
- title ("Unable to Write");
- else
- title ("OK");
- } else {
- title("Unable to open file");
- }
- }
-
- /*
- * Nitty Gritty.
- *
- * keyboard_init: initialize for get_codequal() and cqtoa()
- * get_codequal: convert a qualifier-string combo to a keycode and qual.
- * cqtoa: convert a keycode and qual to a qual & string
- */
-
- #define LN(a,b,c,d) ((a<<24)|(b<<16)|(c<<8)|d)
-
- static long lname[] = {
- LN('e','s','c', 0 ), LN('f','1', 0 , 0 ), LN('f','2', 0 , 0 ),
- LN('f','3', 0 , 0 ), LN('f','4', 0 , 0 ), LN('f','5', 0 , 0 ),
- LN('f','6', 0 , 0 ), LN('f','7', 0 , 0 ), LN('f','8', 0 , 0 ),
- LN('f','9', 0 , 0 ), LN('f','1','0', 0 ), LN('d','e','l', 0 ),
- LN('b','a','c', 0 ), LN('b','s', 0 , 0 ), LN('t','a','b', 0 ),
- LN('h','e','l', 0 ), LN('r','e','t', 0 ), LN('u','p', 0 , 0 ),
- LN('d','o','w', 0 ), LN('r','i','g', 0 ), LN('l','e','f', 0 ),
- LN('e','n','t', 0 ), LN('n','k','-', 0 ), LN('n','k','.', 0 ),
- LN('n','k','0', 0 ), /* 24 */
- LN('n','k','1', 0 ), LN('n','k','2', 0 ), LN('n','k','3', 0 ),
- LN('n','k','4', 0 ), LN('n','k','5', 0 ), LN('n','k','6', 0 ),
- LN('n','k','7', 0 ), LN('n','k','8', 0 ), LN('n','k','9', 0 ),
- LN('n','k','(', 0 ), LN('n','k',')', 0 ), LN('n','k','/', 0 ), /*34-36*/
- LN('n','k','*', 0 ), LN('n','k','+', 0 ),
- LN('l','m','b',0xE8), LN('m','m','b',0xEA), LN('r','m','b',0xE9),
- LN('m','m','o',QMOVE),
- 0
- };
-
-
- /*
- * ESC: x1B
- * FUNCKEYS: x9B 30 7E to x9B 39 7E
- * DEL: x7E
- * BS: x08
- * TAB: x09
- * RETURN: x0D
- * HELP x9B 3F 7E
- * UP/D/L/R x9B 41/42/44/43
- * NK0-9,-,.,ENTER
- *
- * Mouse buttons
- */
-
- void keyboard_init(void)
- {
- static struct InputEvent ievent = { NULL, IECLASS_RAWKEY };
- ubyte buf[32];
- short i, len;
-
- lname[16] |= 0x44;
- lname[21] |= 0x43;
-
- for (i = 0; i < 128; ++i) {
- ievent.ie_Code = i;
- ievent.ie_Qualifier = 0;
- ievent.ie_position.ie_addr = NULL;
- len = RawKeyConvert(&ievent,buf,32,NULL);
- switch(len) {
- case 1: /* ESC/DEL/BS/TAB/NKx */
- if ((buf[0] & 0x7F) >= 32 && (buf[0] & 0x7F) < 127)
- ctoa[i] = buf[0];
- switch(buf[0]) {
- case 0x1B: lname[ 0] |= i; break;
- case 0x7F: lname[11] |= i; break;
- case 0x09: lname[14] |= i; break;
- case 0x08: lname[12] |= i; lname[13] |= i; break;
- case '(': if (i > 0x3A) lname[34] |= i; break;
- case ')': if (i > 0x3A) lname[35] |= i; break;
- case '/': if (i > 0x3A) lname[36] |= i; break;
- case '*': if (i > 0x3A) lname[37] |= i; break;
- case '-': if (i > 0x3A) lname[22] |= i; break;
- case '+': if (i > 0x3A) lname[38] |= i; break;
- case '.': if (i > 0x3A) lname[23] |= i; break;
- default:
- if (i >= 0x0F && buf[0] >= '0' && buf[0] <= '9')
- lname[24+buf[0]-'0'] |= i;
- }
- break;
- case 2: /* cursor */
- if (buf[0] == 0x9B) {
- switch(buf[1]) {
- case 0x41: lname[17] |= i; break;
- case 0x42: lname[18] |= i; break;
- case 0x43: lname[19] |= i; break;
- case 0x44: lname[20] |= i; break;
- }
- }
- break;
- case 3: /* function/help */
- if (buf[0] == 0x9B && buf[2] == 0x7E) {
- if (buf[1] == 0x3F)
- lname[15] |= i;
- if (buf[1] >= 0x30 && buf[1] <= 0x39)
- lname[buf[1]-0x30+1] |= i;
- }
- break;
- }
- }
- for (i = 0; i < 128; ++i) {
- ievent.ie_Code = i;
- ievent.ie_Qualifier = IEQUALIFIER_LSHIFT;
- ievent.ie_position.ie_addr = NULL;
- len = RawKeyConvert(&ievent,buf,32,NULL);
- if (len == 1)
- cstoa[i] = buf[0];
- }
- {
- ubyte code, qual;
- get_codequal("c", &code, &qual);
- CtlC = code;
- }
- }
-
-
- ubyte *cqtoa(int code, int qual)
- {
- static ubyte buf[32];
- ubyte *ptr = buf;
- int i;
-
- if (qual & QUAL_SHIFT)
- *ptr++ = 's';
- if (qual & QUAL_CTRL)
- *ptr++ = 'c';
- if (qual & QUAL_ALT)
- *ptr++ = 'a';
- if (qual & QUAL_AMIGA)
- *ptr++ = 'A';
- if (qual & QUAL_LMB)
- *ptr++ = 'L';
- if (qual & QUAL_MMB)
- *ptr++ = 'M';
- if (qual & QUAL_RMB)
- *ptr++ = 'R';
- if (qual)
- *ptr++ = '-';
- for (i = 0; i < sizeof(lname)/sizeof(lname[0]); ++i) {
- if ((lname[i]&0xFF) == code) {
- *ptr++ = (lname[i]>>24);
- *ptr++ = (lname[i]>>16);
- *ptr++ = (lname[i]>>8);
- break;
- }
- }
- if (i == sizeof(lname)/sizeof(lname[0]))
- *ptr++ = ctoa[code];
- *ptr++ = 0;
- return(buf);
- }
-
-
- int get_codequal(ubyte *str, ubyte *pcode, ubyte *pqual)
- {
- char *base = str;
- ubyte qual;
- short i;
-
- qual = 0;
- if (strlen(str) > 1) {
- for (; *str && *str != '-'; ++str) {
- if (*str == 's')
- qual |= QUAL_SHIFT;
- if (*str == 'c')
- qual |= QUAL_CTRL;
- if (*str == 'a')
- qual |= QUAL_ALT;
- if (*str == 'A')
- qual |= QUAL_AMIGA;
- if (*str == 'L')
- qual |= QUAL_LMB;
- if (*str == 'M')
- qual |= QUAL_MMB;
- if (*str == 'R')
- qual |= QUAL_RMB;
- if (!qual)
- goto notqual;
- }
- if (*str == 0) {
- qual = 0;
- str = base;
- } else {
- ++str;
- }
- }
- notqual:
- if (strlen(str) != 1) { /* long name */
- short shift = 24;
- long mult = 0;
- ubyte c;
-
- *pqual = qual;
- while ((c = *str) && shift >= 8) {
- if (c >= 'A' && c <= 'Z')
- c = c - 'A' + 'a';
- mult |= c << shift;
- shift -= 8;
- ++str;
- }
- for (i = 0; lname[i]; ++i) {
- if (mult == (lname[i] & 0xFFFFFF00)) {
- *pcode = lname[i] & 0xFF;
- return(1);
- }
- }
- } else { /* single character keycap */
- for (i = 0; i < sizeof(ctoa); ++i) {
- if (*str == ctoa[i]) {
- *pcode = i;
- *pqual = qual;
- return(1);
- }
- }
- for (i = 0; i < sizeof(cstoa); ++i) {
- if (*str == cstoa[i]) {
- *pcode = i;
- *pqual = qual|QUAL_SHIFT;
- return(1);
- }
- }
- }
- return(0);
- }
-
-