/* * Keyboard buffer stuffer * * This program copies characters from the command line into the PC * keyboard buffer, adding correct "scan code" extensions as it does so. * Numerous "escape sequences" are recognized to provide for stuffing * non-ASCII characters produced by the various non-alphanumeric keys on * the PC keyboard. * * The default BIOS keyboard buffer holds only 15 entries, however this * program uses the START/END pointers from BIOS, so it should work * correctly with the various utilities that enlarge the buffer. * * Copyright 1994-1995 Dave Dunfield * All rights reserved. * * Permission granted for personal (non-commerical) use only. * * Compile command: CC stuff -fop */ #include #define BIOS_SEG 0x40 /* BIOS data segment */ #define BUFFER_START 0x80 /* Pointer to start of keyboard buffer */ #define BUFFER_END 0x82 /* Pointer to end of keyboard buffer */ #define BUFFER_TAIL 0x1A /* Pointer to next character to receive */ #define BUFFER_HEAD 0x1C /* Pointer to first available spot */ /* Prefix codes for "ALPHA" keys */ char alpha_prefix[] = { 0x1E, 0x30, 0x2E, 0x20, 0x12, 0x21, 0x22, 0x23, 0x17, 0x24, 0x25, 0x26, 0x32, 0x31, 0x18, 0x19, 0x10, 0x13, 0x1F, 0x14, 0x16, 0x2F, 0x11, 0x2D, 0x15, 0x2C }; /* Codes for misc. ASCII keys */ unsigned ascii_prefix[] = { 0x3920, 0x0231, 0x0332, 0x0433, 0x0534, 0x0635, 0x0736, 0x0837, 0x0938, 0x0A39, 0x0B30, 0x0C2D, 0x0D3D, 0x2B5C, 0x297E, 0x0221, 0x0340, 0x0423, 0x0524, 0x0625, 0x0826, 0x092A, 0x0A28, 0x0B29, 0x0C5F, 0x0D2B, 0x2B7C, 0x1A5B, 0x1B5D, 0x273B, 0x2827, 0x332C, 0x342E, 0x352F, 0x1A7B, 0x1B7D, 0x273A, 0x2822, 0x333C, 0x343E, 0x353F, 0x2960, 0 }; /* Table of special keys & codes */ char misc_key[] = { '=', '!', '/', '\\', /* Enter, Backspace, Tab, Backtab */ '@','0','.', '+', '-', /* Escape, Ins, Del, keypad+, keypad- */ '4', '6', '8', '2', /* Right, Left, Up, Down */ '7', '1', '9', '3', /* Home, End, PgUp, PgDn */ '^' }; /* Single '^' */ unsigned misc_code[] = { 0x1C0D, 0x0E08, 0x0F09, 0x0F00, 0x011B, 0x5200, 0x5300, 0x4E2b, 0x4A2D, 0x4B00, 0x4D00, 0x4800, 0x5000, 0x4700, 0x4F00, 0x4900, 0x5100, 0x075E }; /* Help text */ char *help[] = { "\nKeyboard buffer stuffer - by Dave Dunfield\n", "\nUse: stuff \n\n", "^ = special character:\n\n", " ^A-Z Ctrl ^*A-Z Alt ^#0-9 Fn ^$0-9 SFn ^%0-9 CFn ^&0-9 AFn\n\n", " ^. Del ^0 Ins ^1 End ^2 Down ^3 PgDn ^4 Left\n", " ^6 Right ^7 Home ^8 Up ^9 PgUp ^+ Kpad+ ^- Kpad-\n\n", " ^^ (^) ^= Enter ^@ Esc ^! Backsp ^/ Tab ^\\ Backtab\n\n", " ^? Clear keyboard buffer\n", 0 }; /* * Main program - Stuff arguments into the keyboard buffer */ main(int argc, char *argv[]) { int i; if(argc < 2) { /* No data to stuff, display help */ for(i=0; help[i]; ++i) fputs(help[i], stdout); return; } i = 1; while(i < argc) { /* Stuff all arguments */ stuff_string(argv[i]); if(++i < argc) stuff_string(" "); } } /* * Stuff a string into the keyboard buffer */ stuff_string(char *ptr) { int i, j; char c, prefix; while(c = *ptr++) { if(isalpha(c)) /* Normal "ALPHA" character */ prefix = alpha_prefix[(c & 0x1F) - 1]; else if(c == '^') { if(isalpha(c = *ptr++)) /* ALPHA control code */ prefix = alpha_prefix[(c &= 0x1F) - 1]; else switch(c) { default: for(i=0; i < sizeof(misc_key); ++i) if(c == misc_key[i]) { stuff_key(misc_code[i]); goto done; } clear_buffer(); abort("Unknown ^!\n"); case '#' : /* Normal function key */ prefix = 0x3B; goto dofunc; case '$' : /* Shift function key */ prefix = 0x54; goto dofunc; case '%' : /* CTRL function key */ prefix = 0x5E; goto dofunc; case '&' : /* ALT function key */ prefix = 0x68; dofunc: if(isdigit(c = *ptr++)) { prefix += (c == '0') ? 9 : (c - '1'); c = 0; break; } clear_buffer(); abort("Fkey must be 0-9\n"); case '?' : /* Clear buffer */ clear_buffer(); continue; case '*' : /* ALT-ALPHA character */ prefix = alpha_prefix[(*ptr++ & 0x1F) - 1]; c = 0; } } else { for(i=0; j = ascii_prefix[i]; ++i) if((j & 255) == c) { stuff_key(j); goto done; } clear_buffer(); abort("Unknown character\n"); } stuff_key((prefix << 8) | c); done: } } /* * Stuff a single keystroke into the keyboard buffer */ stuff_key(unsigned key) { unsigned head; disable(); pokew(BIOS_SEG, head = peekw(BIOS_SEG, BUFFER_HEAD), key); if((head += 2) >= peekw(BIOS_SEG, BUFFER_END)) head = peekw(BIOS_SEG, BUFFER_START); if(head == peekw(BIOS_SEG, BUFFER_TAIL)) { clear_buffer(); abort("Key buffer FULL!\n"); } if(head != peekw(BIOS_SEG, BUFFER_TAIL)) pokew(BIOS_SEG, BUFFER_HEAD, head); enable(); } /* * Clear the keyboard buffer */ clear_buffer() { disable(); pokew(BIOS_SEG, BUFFER_HEAD, peekw(BIOS_SEG, BUFFER_TAIL)); enable(); }