/* * keybrd.pc: * functions, maps and interrupt handlers for IBM PC keyboards * * Copyright (c) 1989 University of Toronto. All rights reserved. * Anyone may use or copy this software, except that it may not be * sold for profit, that this copyright notice remain intact, and that * credit is given where it is due. The University of Toronto and the * author make no warranty and accept no liability for this software. */ static char rcsid[] = "$Header: /homes/ugw/pkern/src/cterm/RCS/keybrd.pc,v 1.6 89/10/04 19:49:57 pkern Exp $"; #include #include "cterm.h" #include "pc.h" #define word unsigned int uchar keyboom=0; static union REGS r; static uchar f_map=0, f_vec=0, kb_mode=0; extern uchar flowctl, local, xoff; #ifdef KB_INT #define INTA00 0x20 #define KB_DATA 0x60 #define KB_CTL 0x61 #define EOI 0x20 static word scan[85 * 5] = { /* scan code re-map table */ /* map-codes (norm, shift, ctrl, alt) & hit-flag */ 0, 0, 0, 0, 0, #ifdef MVESC 0x8c00, 0x8c00, 0x8c00, 0x8c00, 0, /* Esc -> PF1 */ #else 27, 27, 27, 0, 0, /* Esc */ #endif '1', '!', 0, 0x7800, 0, '2', '@', 0x300, 0x7900, 0, '3', '#', 0, 0x7a00, 0, '4', '$', 0, 0x7b00, 0, '5', '%', 0, 0x7c00, 0, '6', '^', 0x1e, 0x7d00, 0, '7', '&', 0, 0x7e00, 0, '8', '*', 0, 0x7f00, 0, '9', '(', 0, 0x8000, 0, '0', ')', 0, 0x8100, 0, '-', '_', 0x1f, 0x8200, 0, '=', '+', 0, 0x8300, 0, 8, 8, 127, 127, 0, /* backspace */ 9, 0x0f00, 0, 0, 0, /* tab */ /* 0x10 */ 'q', 'Q', 0x11, 0x1000, 0, 'w', 'W', 0x17, 0x1100, 0, 'e', 'E', 0x05, 0x1200, 0, 'r', 'R', 0x12, 0x1300, 0, 't', 'T', 0x14, 0x1400, 0, 'y', 'Y', 0x19, 0x1500, 0, 'u', 'U', 0x15, 0x1600, 0, 'i', 'I', 0x09, 0x1700, 0, 'o', 'O', 0x0f, 0x1800, 0, 'p', 'P', 0x10, 0x1900, 0, '[', '{', 0x1b, 0, 0, ']', '}', 0x1d, 0, 0, 13, 13, 10, 0, 0, /* return */ #define CTRL 149 /* 29 * 5 + 4 */ 0, 0, 0, 0, 0, /* CTRL */ 'a', 'A', 0x01, 0x1e00, 0, 's', 'S', 0x13, 0x1f00, 0, /* 0x20 */ 'd', 'D', 0x04, 0x2000, 0, 'f', 'F', 0x06, 0x2100, 0, 'g', 'G', 0x07, 0x2200, 0, 'h', 'H', 0x08, 0x2300, 0, 'j', 'J', 0x0a, 0x2400, 0, 'k', 'K', 0x0b, 0x2500, 0, 'l', 'L', 0x0c, 0x2600, 0, ';', ':', 0, 0, 0, '\'', '"', 0, 0, 0, '`', '~', 0, 0, 0, #define LSHIFT 214 /* 42 * 5 + 4 */ 0, 0, 0, 0, 0, /* left SHIFT */ '\\', '|', 0x1c, 0, 0, 'z', 'Z', 0x1a, 0x2c00, 0, 'x', 'X', 0x18, 0x2d00, 0, 'c', 'C', 0x03, 0x2e00, 0, 'v', 'V', 0x16, 0x2f00, 0, /* 0x30 */ 'b', 'B', 0x02, 0x3000, 0, 'n', 'N', 0x0e, 0x3100, 0, 'm', 'M', 0x0d, 0x3200, 0, ',', '<', 0, 0, 0, '.', '>', 0, 0, 0, '/', '?', 0, 0, 0, #define RSHIFT 274 /* 54 * 5 + 4 */ 0, 0, 0, 0, 0, /* right SHIFT */ 0x7200, 0x7200, 0x7200, 0x7200, 0, /* PrtSc/* -> - */ /* '*', 0, 0, 0, 0, /* PrtSc/* */ #define ALT 284 /* 56 * 5 + 4 */ 0, 0, 0, 0, 0, /* ALT */ ' ', ' ', 0x300, ' ', 0, /* space bar */ #define CAPS 294 /* 58 * 5 + 4 */ 0, 0, 0, 0, 0, /* Caps Lock */ 0x3b00, 0x5400, 0x5e00, 0x6800, 0, /* F1 */ #ifdef MVESC 27, 27, 27, 0, 0, /* F2 -> Esc */ #else 0x3c00, 0x5500, 0x5f00, 0x6900, 0, /* F2 */ #endif 0x3d00, 0x5600, 0x6000, 0x6a00, 0, /* F3 */ 0x3e00, 0x5700, 0x6100, 0x6b00, 0, /* F4 */ 0x3f00, 0x5800, 0x6200, 0x6c00, 0, /* F5 */ /* 0x40 */ 0x4000, 0x5900, 0x6300, 0x6d00, 0, /* F6 */ 0x4100, 0x5a00, 0x6400, 0x6e00, 0, /* F7 */ 0x4200, 0x5b00, 0x6500, 0x6f00, 0, /* F8 */ 0x4300, 0x5c00, 0x6600, 0x7000, 0, /* F9 */ 0x4400, 0x5d00, 0x6700, 0x7100, 0, /* F10 */ 0x8d00, 0x8d00, 0x8d00, 0x8d00, 0, /* Num Lock/Pause -> PF2 */ 0x8e00, 0x8e00, 0x100, 0x8e00, 0, /* Scroll Lock/Break -> PF3 */ 0x4700, 0x4700, 0x7700, 0x4700, 0, /* 7/Home */ 0x4800, 0x4800, 0x4800, 0x6e00, 0, /* 8/ */ 0x4900, 0x4900, 0x8400, 0x4900, 0, /* 9/PgUp */ 0x4a00, 0x4a00, 0x4a00, 0x4a00, 0, /* - -> ' */ 0x4b00, 0x4b00, 0x7300, 0x7000, 0, /* 4/ */ 0x4c00, 0x4c00, 0x4c00, 0x4c00, 0, /* 5 */ 0x4d00, 0x4d00, 0x7400, 0x7100, 0, /* 6/ */ 0x4e00, 0x4e00, 0x4e00, 0x4e00, 0, /* + -> ENTER */ 0x4f00, 0x4f00, 0x7500, 0x4f00, 0, /* 1/End */ /* 0x50 */ 0x5000, 0x5000, 0x5000, 0x6f00, 0, /* 2/ */ 0x5100, 0x5100, 0x7600, 0x5100, 0, /* 3/PgDn */ 0x5200, 0x5200, 0x5200, 0x5200, 0, /* 0/Ins */ 0x5300, 0x5300, 0x5300, 0x5300, 0, /* ./Del */ 0x8f00, 0x8f00, 0x8f00, 0x8f00, 0 /* Sys Req -> PF4 */ }; static word keybuf[256]; static uchar kbin=0, kbout=0, autorep; void interrupt (*o_int)(); void interrupt k_int(bp, di, si, ds, es, dx, cx, bx, ax) word bp, di, si, ds, es, dx, cx, bx, ax; { uchar ctl; word code, hit; code = inportb(KB_DATA); ctl = inportb(KB_CTL); outportb(KB_CTL, ctl | 0x80); outportb(KB_CTL, ctl); enable(); ctl = code; code = (code & 0x7f) * 5; hit = ((ctl & 0x80) == 0); /* 0x80: key up */ if (!hit || !scan[code]) { /* key has just lifted or it's a "shift" key */ code += 4; scan[code] = hit; ctl = 0; switch (code) { case ALT: ctl = 0x08; break; case CTRL: ctl = 0x04; break; case LSHIFT: ctl = 0x02; break; case RSHIFT: ctl = 0x01; break; case CAPS: ctl = 0x40; hit = (scan[CAPS-1] ^= hit); break; } if (ctl) { if (hit) kb_mode |= ctl; else kb_mode &= ~ctl; } } else if (!scan[code+4] || autorep) { scan[code+4] = hit; ctl = kb_mode & 0x43; if (kb_mode & 0x08) /* ALT */ code += 3; else if (kb_mode & 0x04) /* CTRL */ code += 2; else if (ctl == 0x40) /* CAPS */ code += 1; else if (0 < ctl && ctl < 4) /* SHIFT */ code += 1; code = scan[code]; if (code & 0xf0ff) keybuf[kbin++] = code; else switch (code >> 8) { /* special ! */ case 1: /* Ctrl Break */ keyboom++; /* we go bye now! */ break; case 0x3: /* ctrl-2@, ctrl-space */ case 0xf: /* back-tab */ keybuf[kbin++] = code; break; default: break; } } outportb(INTA00, EOI); } kbdhit() { return(kbin != kbout); } kbflush() { kbin = kbout; } kbautorep(sw) int sw; { autorep = sw; } word kbdget() { if (f_vec) return(keybuf[kbout++]); /* else use regular bios */ r.h.ah = 0; int86(KBD_INT, &r, &r); if (r.x.ax & 0xff) r.x.ax &= 0xff; return((word) r.x.ax); } #else /* KB_INT */ /* check for queued keys */ kbdhit() { r.h.ah = 1; int86(KBD_INT, &r, &r); return (!(r.x.flags & Zflag)); /* ie. ! Z-flag */ } /* flush keyboard type-ahead queue */ kbflush() { r.h.ah = 3; int86(KBD_INT, &r, &r); } /* toggle keyboard autorepeat */ kbautorep(sw) int sw; /* switch : 1 = on, 0 = off */ { r.h.ah = 4; r.h.al = (sw) ? 1 : 2; int86(KBD_INT, &r, &r); } /* get keyboard word */ word kbdget() { r.h.ah = 2; int86(KBD_INT, &r, &r); kb_mode = r.h.al; r.h.ah = 0; int86(KBD_INT, &r, &r); if (r.x.ax & 0xff) r.x.ax &= 0xff; return((word) r.x.ax); } #endif /* KB_INT */ /* return a keypadv[] offset | 8-bit alternative */ kbdfn(kn) word kn; { word fn; extern word keymap[], alt8[]; kn = kn >> 8; fn = alt8[kn] & 0x7f; if (fn) { if (kb_mode & 0x04) /* Ctrl key */ fn = (alt8[kn] >> 8) & 0x3f; else if (kb_mode & 0x03) /* Shift keys */ fn = alt8[kn] >> 8; fn |= 0x80; } return((fn << 8) | keymap[kn]); } /* * keypad map (aN == alt N) * +-----+-----+-----+-----+ * | PF1 | PF2 | PF3 | PF4 | cursor code offsets: * | aF1 | aF2 | aF3 | aF4 | UP - 0 * +-----+-----+-----+-----+ DOWN - 1 * | 7 | 8 | 9 | - | RIGHT - 2 * | a1 | a2 | a3 | a4 | LEFT - 3 * +-----+-----+-----+-----+ * | 4 | 5 | 6 | , | keypad code string offsets: * | aQ | aW | aE | aR | 8 - "0" 10 - "8" 18 - "F3" * +-----+-----+-----+-----+ 9 - "1" 11 - "9" 19 - "F4" * | 1 | 2 | 3 | | A - "2" 12 - "-" 1A - "\200" * | aA | aS | aD |Enter| B - "3" 13 - "," 1B - "\b" * +-----+-----+-----+ | C - "4" 14 - "." 1C - "\003" * | 0 | . | aF | D - "5" 15 - "ENTER" 1D - "\r\n" * | aZ aX | aC | aV | E - "6" 16 - "F1" 1E *-> ansback * +-----------+-----+-----+ F - "7" 17 - "F2" 1F - "" (empty) */ /* * keymap: * keypadv[] offsets for all extended function codes */ static word keymap[0x90] = { /* 0x0_ */ 0x1f, 0x1f, 0x1f, 0x1a, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x03, /* 0x1_ */ 0x0c, 0x0d, 0x0e, 0x13, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x09, 0x0a, /* 0x2_ */ 0x0b, 0x15, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x08, 0x08, 0x14, 0x15, /* 0x3_ */ 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1b, 0x1f, /* 0x4_ */ 0x1f, 0x00, 0x01, 0x03, 0x02, 0x1f, 0x1f, 0x0f, 0x10, 0x11, 0x13, 0x0c, 0x0d, 0x0e, 0x15, 0x09, /* 0x5_ */ 0x0a, 0x0b, 0x08, 0x14, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x00, 0x01, 0x03, 0x02, 0x1f, 0x1f, /* 0x6_ */ 0x1f, 0x1f, 0x1f, 0x1f, 0x00, 0x01, 0x03, 0x02, 0x16, 0x17, 0x18, 0x19, 0x1f, 0x1f, 0x00, 0x01, /* 0x7_ */ 0x03, 0x02, 0x12, 0x03, 0x02, 0x1f, 0x01, 0x1f, 0x0f, 0x10, 0x11, 0x12, 0x1f, 0x1f, 0x1f, 0x1f, /* 0x8_ */ 0x1f, 0x1f, 0x1f, 0x1f, 0x00, 0x1f, 0x1f, 0x1f, 0x00, 0x01, 0x02, 0x03, 0x16, 0x17, 0x18, 0x19 }; /* * alt8: * keymap[] ALTernative with 8th bit set * (Turbo C direct storage: 'lsb msb') */ static word alt8[0x90] = { /* 0x0_ */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x1_ */ 'qQ', 'wW', 'eE', 'rR', 'tT', 'yY', 'uU', 'iI', 'oO', 'pP', 0, 0, 0, 0, 'aA', 'sS', /* 0x2_ */ 'dD', 'fF', 'gG', 'hH', 'jJ', 'kK', 'lL', 0, 0, 0, 0, 0, 'zZ', 'xX', 'cC', 'vV', /* 0x3_ */ 'bB', 'nN', 'mM', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x4_ */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x5_ */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x6_ */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x7_ */ 0, 0, 0, 0, 0, 0, 0, 0, '1!', '2@', '3#', '4$', '5%', '6^', '7&', '8*', /* 0x8_ */ '9(', '0)', '-_', '=+', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; /* k_brk -- intercept Ctrl-Break interrupt */ void interrupt k_brk(bp,di,si,ds,es,dx,cx,bx,ax,ip,cs,flags) word bp,di,si,ds,es,dx,cx,bx,ax,ip,cs,flags; { send_brk(); flags |= Cflag; /* ie. don't queue it */ keyboom++; } /* * o_brk : temp storage for old interrupt vectors */ void interrupt (*o_brk)(); init_kbd() { if (f_vec) return(0); kbflush(); /* remember old intr vector(s) */ o_brk = getvect(KEYBRK); #ifdef KB_INT o_int = getvect(KB_INT); #endif /* install new one(s) */ disable(); setvect(KEYBRK, k_brk); #ifdef KB_INT setvect(KB_INT, k_int); #endif enable(); f_vec = 1; /* vector(s) installed */ /* some important key mappings */ keymap[K_SETUP >> 8] = 0x80; /* flag the SETUP key */ #ifndef MVESC keymap[(K_SETUP >> 8)+1] = 0x80; /* ditto on F2 */ #endif keymap[K_shBRK >> 8] = 0x40; /* shiftBrk - hang up */ keymap[K_NUL >> 8] = 0x41; /* ctrl-2@ - send NUL */ keymap[K_BREAK >> 8] = 0x42; /* BREAK - send BREAK */ keymap[K_BKSP >> 8] = 0x1b; /* backsp keypadv[] position */ keymap[K_cBRK >> 8] = 0x1e; /* ctrlBrk keypadv[] position */ keyboom = 0; } reset_kbd() { if (!f_vec) return; /* no vectors to reset, yet */ kbflush(); /* restore old intr vector(s) */ disable(); setvect(KEYBRK, o_brk); #ifdef KB_INT setvect(KB_INT, o_int); #endif enable(); f_vec = 0; /* vector(s) reset */ } /* switch newline mode */ nlmod(sw) uchar sw; { /* shift ENTER offset, if needed */ keymap[0x21] = keymap[0x2f] = ((sw) ? 0x1d : 0x15); }