Annotation of coherent/b/kernel/FWB/interfac.c, revision 1.1.1.1

1.1       root        1: /*-----------------------------------------------------------------------------
                      2:        Talking BIOS device driver for the AT&T PC6300.
                      3:        Copyright (C) Karl Dahlke 1987
                      4:        This software may be freely used and distributed
                      5:        for any non-profit purpose.
                      6:  *-----------------------------------------------------------------------------
                      7:  */
                      8: 
                      9: /* interfac.c: interface function to kernel and device drivers */
                     10: 
                     11: /* This file contains routines to speak letters, words, single lines,
                     12:  * and the entire screen/buffer.
                     13:  * These routines are called at interrupt level, but they may take
                     14:  * as long as they wish.  A frozen view of pointers is presented,
                     15:  * and I know of no way they can change while these routines are executing
                     16:  * (though there may be an obscure scenario).
                     17:  * A separate stack of around 200 bytes is provided,
                     18:  * but there's no stack checking, so be careful.
                     19:  * Also, this stack is not aligned with the data segment,
                     20:  * so don't use the address of any auto variable.
                     21:  */
                     22: 
                     23: #include "speech.h"
                     24: 
                     25: /* control variables for each of 5 concurrent sessions: console + 4 comports */
                     26: struct SDCONTROL *sdcontrol[5];
                     27: struct SDCONTROL *sdc; /* set to sdcontrol[sdsession] */
                     28: int sdsession; /* current session, 0 for the console, 1-4 for the comports */
                     29: char sdw[WORDLEN*2]; /* word to be spoken */
                     30: 
                     31: /* patchable variables that establish synthesizer, comport,
                     32:  * and size of internal circular buffer, for each of 5 possible sessions.
                     33:  * The 5 configured synthesizers */
                     34: int sd0synth = 0, sd1synth = 0, sd2synth = 0, sd3synth = 0, sd4synth = 0;
                     35: int sd0comport = 0, sd1comport = 0, sd2comport = 0, sd3comport = 0, sd4comport = 0;
                     36: unsigned short sd0cbufsz = 0, sd1cbufsz = 0, sd2cbufsz = 0, sd3cbufsz = 0, sd4cbufsz = 0;
                     37: 
                     38: #ifdef MSDOS
                     39: static char far *doslineptr;
                     40: skipwhite()
                     41: {
                     42: char c;
                     43: c = *doslineptr;
                     44: while(c == ' ' || c == '\t') c = *++doslineptr;
                     45: } /* skipwhite */
                     46: 
                     47: /* a version of strtol, to help crack the dos parameters */
                     48: static unsigned short nextparm()
                     49: {
                     50: unsigned short n = 0;
                     51: char c;
                     52: 
                     53: skipwhite();
                     54: c = *doslineptr;
                     55: 
                     56: while(isdigit(c)) {
                     57: n = 10*n + c - '0';
                     58: c = *++doslineptr;
                     59: } /* n is built */
                     60: 
                     61: return n;
                     62: } /* nextparm */
                     63: 
                     64: /* interpret line in config.sys, DOS only.
                     65:  * Coherent just patches the global variables to set parameters. */
                     66: dosline(line)
                     67: char far *line;
                     68: {
                     69: char c;
                     70: 
                     71: /* skip past command name and set doslineptr */
                     72: c = *line;
                     73: while(c != ' ' && c != '\t' && c != '\r')
                     74: c = *++line;
                     75: doslineptr = line;
                     76: 
                     77: sd0cbufsz = nextparm();
                     78: sd0comport = nextparm();
                     79: sd0synth = nextparm();
                     80: 
                     81: skipwhite();
                     82: c = *doslineptr;
                     83: if(c != '\r') /* error message about command line format */;
                     84: } /* dosline */
                     85: #endif
                     86: 
                     87: /* interface function, called from isload() */
                     88: sdload()
                     89: {
                     90: char *bufstart;
                     91: int i;
                     92: unsigned short reqsz;
                     93: struct SDCONTROL *o;
                     94: extern isin();
                     95: static char defkeymap[] = {
                     96: 12,13,14,15,16,
                     97: 17,18,23,22,28};
                     98: static char defpuncmap[] = "\
                     99: null~~~~~~\
                    100: escape~~~~\
                    101: askie 1c~~\
                    102: askie 1d~~\
                    103: askie 1e~~\
                    104: askie 1f~~\
                    105: space~~~~~\
                    106: bang~~~~~~\
                    107: quoat~~~~~\
                    108: pound~~~~~\
                    109: doller~~~~\
                    110: percent~~~\
                    111: and~~~~~~~\
                    112: single~~~~\
                    113: left paren\
                    114: rite paren\
                    115: star~~~~~~\
                    116: plus~~~~~~\
                    117: comma~~~~~\
                    118: mighnus~~~\
                    119: periud~~~~\
                    120: slash~~~~~\
                    121: colen~~~~~\
                    122: semmy~~~~~\
                    123: less~~~~~~\
                    124: eequal~~~~\
                    125: greater~~~\
                    126: question~~\
                    127: at sign~~~\
                    128: left b~~~~\
                    129: backslash~\
                    130: rite b~~~~\
                    131: up airow~~\
                    132: underline~\
                    133: backquoat~\
                    134: left brace\
                    135: vertical~~\
                    136: rite brace\
                    137: tillda~~~~\
                    138: deleet~~~~\
                    139: ";
                    140: 
                    141: /* allocate word replacement and macro definition areas */
                    142: sdtblload();
                    143: 
                    144: for(i=0; i<5; ++i) {
                    145: sdsynth_init(i);
                    146: if(!(o = sdcontrol[i])) continue; /* kalloc failed */
                    147: 
                    148: /* I/O functions. */
                    149: o->dev_in = isin;
                    150: 
                    151: /* initialize the punctuation pronunciation table */
                    152: memcpy(o->punctab, defpuncmap, 40*10);
                    153: 
                    154: /* initialize the key mappings */
                    155: memcpy(o->keymap+0x3b, defkeymap, 10);
                    156: 
                    157: /* circular buffer */
                    158: reqsz = (&sd0cbufsz)[i];
                    159: if(reqsz < 400) reqsz = 400;
                    160: if(!(bufstart = kalloc(reqsz))) {
                    161: reqsz = sizeof(o->defcbuf);
                    162: bufstart = o->defcbuf;
                    163: }
                    164: o->bufbot =
                    165: o->bufhead =
                    166: o->buftail =
                    167: o->bufcur =
                    168: bufstart;
                    169: o->buftop = bufstart + reqsz;
                    170: 
                    171: /* modes that are set */
                    172: o->dev_ok = 1;
                    173: o->buf_ok = 1;
                    174: } /* end loop initializing structures */
                    175: 
                    176: /* startup sound.
                    177:  * More than just cute, we need to do this, or something like it,
                    178:  * to enable the speaker, so that subsequen noises,
                    179:  * produce by system output, before going multiuser,
                    180:  * generates audio feedback. */
                    181: sdsound(8);
                    182: } /* sdload */
                    183: 
                    184: #ifndef MSDOS
                    185: /* interface function, called from isuload() */
                    186: sduload()
                    187: {
                    188: int i;
                    189: struct SDCONTROL *o;
                    190: 
                    191: for(i=0; i<5; ++i) {
                    192: if(!(o = sdcontrol[i])) continue;
                    193: if(o->bufbot != o->defcbuf)
                    194: kfree(o->bufbot);
                    195: kfree(o);
                    196: sdcontrol[i] = 0;
                    197: } /* end loop over sessions */
                    198: } /* sduload */
                    199: #endif
                    200: 
                    201: /* interface function, executed every 0.01 or 0.055 seconds */
                    202: sdtime()
                    203: {
                    204: int session, c;
                    205: struct SDCONTROL *o;
                    206: 
                    207: chkfifo();
                    208: 
                    209: if(!sdready()) return;
                    210: 
                    211: for(session=0; session<5; ++session) {
                    212: o = sdcontrol[session];
                    213: if(!o || o->xparent) continue;
                    214: 
                    215: #ifdef MSDOS
                    216: if(o->dumping) {
                    217: while(1) {
                    218: c = getc();
                    219: if((*o->dev_in)(c)) break;
                    220: if(incptr()) { /* we're done */
                    221: o->dumping = 0;
                    222: sdtext("o k");
                    223: }
                    224: }
                    225: continue;
                    226: } /* dumping text */
                    227: #endif
                    228: 
                    229: if(o->talkcmd) {
                    230: /* check for interrupted speech */
                    231: if(draincheck(o)) {
                    232: sdshutup();
                    233: o->drain_lbolt = 0;
                    234: }
                    235: 
                    236: if(keycmd_start(session, 0)) {
                    237: c = o->talkcmd;
                    238: o->talkcmd = 0;
                    239: keycmd( 128 | c);
                    240: keycmd_end();
                    241: }
                    242: 
                    243: continue;
                    244: } /* o->talkcmd set */
                    245: 
                    246: if(o->rdflag | o->onesymb) {
                    247: if(keycmd_start(session, 0)) {
                    248: reading();
                    249: keycmd_end();
                    250: }
                    251: }
                    252: } /* end loop over 5 sessions */
                    253: } /* sdtime */
                    254: 
                    255: /* before a byte is written to the screen,
                    256:  * place it in the internal circular buffer.
                    257:  * runs with interrupts off. */
                    258: static bufstore(o, c)
                    259: struct SDCONTROL *o;
                    260: char c;
                    261: {
                    262: char *bufbot = o->bufbot, *buftop = o->buftop,
                    263: *bufhead = o->bufhead, *buftail = o->buftail,
                    264: *bufcur = o->bufcur;
                    265: char *t;
                    266: 
                    267: if(!o->ctrl_ok && c != 7 && c != '\r') {
                    268: /* control h removes the last byte in the buffer */
                    269: if(c == 8 && bufhead != buftail) {
                    270: if((t = bufhead) == bufbot) t = buftop;
                    271: if(*--t != '\r') {
                    272: /* ok to back up */
                    273: bufhead = t;
                    274: if(t == bufcur && t != buftail) {
                    275: if(t == bufbot) t = buftop;
                    276: bufcur = --t;
                    277: }
                    278: }
                    279: } /* backing up for control-h */
                    280: 
                    281: if(c < ' ') goto done;
                    282: } /* control charactercheck */
                    283: 
                    284: t = bufhead;
                    285: *t = c;
                    286: if(++t == buftop) t = bufbot;
                    287: bufhead = t;
                    288: if(t == buftail) { /* buffer full */
                    289: /* drop oldest character */
                    290: if(++t == buftop) t = bufbot;
                    291: if(buftail == bufcur) bufcur = t;
                    292: buftail = t;
                    293: } /* full buffer */
                    294: 
                    295: done: /* copy pointers */
                    296: o->bufcur = bufcur;
                    297: o->bufhead = bufhead;
                    298: o->buftail = buftail;
                    299: } /* bufstore */
                    300: 
                    301: /* interface routine, called from mmgo1() or ih_bsc() */
                    302: /* bits returned mean:
                    303:  * 0: display character on device
                    304:  * 1: display an escape before displaying the character
                    305:  * 2: need to take a 10ms real time break before processing this character.
                    306:  * 3: musical output, take a longer real time break. */
                    307: int sdoutchar(session, c)
                    308: short session;
                    309: char c;
                    310: {
                    311: struct SDCONTROL *o = sdcontrol[session];
                    312: short istate;
                    313: int rc = 0;
                    314: 
                    315: if(!o) return 1; /* not active */
                    316: 
                    317: c &= 0x7f;
                    318: 
                    319: if(!o->xparent) {
                    320: /* check for esc{x sequences */
                    321: if(o->esc_lc) {
                    322: o->esc_lc = 0;
                    323: c-='@';
                    324: if(!o->dumping && c > 0 && c < N_CMDS)
                    325: multikey(session, 0, 0, c);
                    326: return 0;
                    327: }
                    328: 
                    329: if(o->esc) {
                    330: o->esc = 0;
                    331: if(c == '{') {
                    332: o->esc_lc = 1;
                    333: return 0;
                    334: } else rc = 2;
                    335: } else {
                    336: if(multikey(session, 0, c, 0))
                    337: return 0;
                    338: }
                    339: 
                    340: if(c == '\033') {
                    341: o->esc = 1;
                    342: if(!rc) return 0;
                    343: rc = 0;
                    344: }
                    345: } /* end transparent mode check */
                    346: 
                    347: if(o->buf_ok) {
                    348: /* Coherent could run bufstore() with interrupts on, but MSDOS cannot.
                    349:  * This is because a sdtime() reading function could take place
                    350:  * during a real time interrupt, while the head/tail buffer
                    351:  * pointers are being modified. */
                    352: #ifdef MSDOS
                    353: istate = sphi();
                    354: #endif
                    355: if(rc) bufstore(o, '\033');
                    356: bufstore(o, c);
                    357: #ifdef MSDOS
                    358: spl(istate);
                    359: #endif
                    360: }
                    361: 
                    362: if(o->xparent) return 1;
                    363: 
                    364: if(o->dev_ok) rc |= 1;
                    365: else rc = 0;
                    366: 
                    367: if(!session) {
                    368: /* make sound accompanying output byte */
                    369: if(sdnoises|sdtones)
                    370: rc |= sdcharsnd(c);
                    371: if(c == 7) rc &= 0xe;
                    372: }
                    373: 
                    374: return rc;
                    375: } /* sdoutchar */
                    376: 
                    377: /* entered character, via keyboard or terminal.
                    378:  * do not call this if the session is null, because
                    379:  * this routine is suppose to call the lower level keyboard input routine.
                    380:  * Note the difference between input and output.
                    381:  * In output, we return 1 and let the calling
                    382:  * routine display the character by calling its own device driver routines.
                    383:  * But on input, we might want to expand a macro, sending a string of
                    384:  * accumulated characters to the input queue.
                    385:  * So we set o->dev_in to the appropriate device driver input
                    386:  * routine, and invoke it as needed. */
                    387: sdinkey(session, key)
                    388: short session;
                    389: short key;
                    390: {
                    391: struct SDCONTROL *o = sdcontrol[session];
                    392: short rc;
                    393: short cmd, xcmd;
                    394: 
                    395: if(o->dumping) {
                    396: if(key == '\33') { /* break out of dumping mode */
                    397: o->dumping = 0;
                    398: }
                    399: return;
                    400: }
                    401: 
                    402: /* hardcoded transparent mode toggle, cannot be reassigned */
                    403: if(key == 0x8300) {
                    404: o->xparent ^= 1;
                    405: if(!session) sdsound(o->xparent+5);
                    406: return;
                    407: }
                    408: 
                    409: xcmd = cmd = transkey(key);
                    410: if(cmd) cmd = o->keymap[cmd];
                    411: 
                    412: if(rc = multikey(session, 1, key, cmd)) {
                    413: if(!session) sdsound(rc);
                    414: } else {
                    415: mexpand(session, key, xcmd);
                    416: }
                    417: } /* sdinkey */
                    418: 
                    419: #ifndef MSDOS
                    420: /* The prexisting system was written for Dos, with Dos key conventions in place.
                    421:  * In order to use the same software, I convert the Coherent representation
                    422:  * of key codes into Dos representation.  My appologies to you purists.
                    423:  * Thus function and alt keys become 0 followed by the scan code.
                    424:  * Coherent doesn't allow for shift-fkey or ctrl-fkey, but the Dos
                    425:  * driver lets you map speech to these keys.  Coherent must therefore pass the
                    426:  * shift state in, so that we can check for shift-F3 etc. */
                    427: sdinkey_coh(c, scan, shift)
                    428: {
                    429: short key;
                    430: static char numpad[] = "789x456x1230.";
                    431: char numlock;
                    432: 
                    433: key = c;
                    434: 
                    435: /* check for Coherent special code or alt key, indicated by the sign bit */
                    436: if(c&0x80) {
                    437: if(scan >= 59 && scan <= 68) { /* function key */
                    438: /* adjust scan codes, for shift or control or alt.
                    439:  * Check with Coherent kb.c to make sure the bits in shift are correct. */
                    440: if(shift&8) scan += 0x2d;
                    441: else if(shift & 4) scan += 0x23;
                    442: else if(shift & 3) scan += 0x19;
                    443: } /* end fkey */
                    444: 
                    445: /* scan code now the same as Dos */
                    446: key = scan<<8;
                    447: 
                    448: /* turn numlock-keypad back to a number */
                    449: if(scan >= 71 && scan <= 83) { /* on the keypad */
                    450: /* exactly one of numlock and shift should be set */
                    451: numlock = shift | (shift>>1);
                    452: numlock ^= (shift >> 5);
                    453: numlock &= ~(shift>>6);
                    454: if(numlock) key = numpad[scan-71];
                    455: } /* end keypad */
                    456: } /* end special code */
                    457: 
                    458: /* call sdinkey if the session is active and not in transparent mode,
                    459:  * or if this key would release an active session from transparent mode */
                    460: if(sdcontrol[0] &&
                    461: (!sdcontrol[0]->xparent || key == 0x8300)) {
                    462: sdinkey(0, key);
                    463: return 1;
                    464: }
                    465: 
                    466: return 0; /* you handle it */
                    467: } /* sdinkey_coh */
                    468: #endif
                    469: 
                    470: /* is this key part of a multikey sequence?
                    471:  * Return nonzero iff this key is absorbed.
                    472:  * This nonzero value also indicates the sound (e.g. error tone) that should be produced.
                    473:  * A return value of 1 requires no sound. */
                    474: static multikey(session, input, key, cmd)
                    475: short session;
                    476: /* Are we processing input or output characters?
                    477:  * If the characters represent input, entered from the keyboard,
                    478:  * this routine is running at interrupt level.
                    479:  * Output comes from the device driver, at process level. */
                    480: char input;
                    481: /* The character entered at the keyboard (input = 1)
                    482:  * or produced by the running process (input = 0) and destined for the screen.
                    483:  * For evolutionary reasons, we follow the DOS convention for
                    484:  * representing special input characters.  Thus F1 = 0x3b00. */
                    485: short key;
                    486: /* Instead of an output character, we may send a command directly,
                    487:  * as when esc{A is translated into a speech command. */
                    488: char cmd;
                    489: {
                    490: struct SDCONTROL *o = sdcontrol[session];
                    491: struct MULTIKEY *a = input ? &o->indata : &o->outdata;
                    492: char lastcmd, c;
                    493: short i, rc;
                    494: struct SDCMD *cmdp;
                    495: 
                    496: rc = 0;
                    497: if(!o->xparent) {
                    498: if(a->nextchar | a->nextline) {
                    499: cmd = 0;
                    500: rc = 1;
                    501: lastcmd = a->lastcmd;
                    502: a->nextchar = 0;
                    503: a->support = key;
                    504: c = key;
                    505: if(!c && lastcmd != 20 && lastcmd != 21)
                    506: return 3;
                    507: 
                    508: if(a->nextline) {
                    509: if(c == '\33') { a->nextline = 0; return 2; }
                    510: /* input line becomes null-terminated string */
                    511: if(c == '\r' || c == '\n') c = 0;
                    512: i = a->textlen;
                    513: a->text[i] = c;
                    514: if(c) {
                    515: if(++i == LINELEN)
                    516: return 4;
                    517: a->textlen = i;
                    518: return 1;
                    519: } /* test for cr */
                    520: a->nextline = 0;
                    521: rc = 2;
                    522: } /* absorbing a line */
                    523: cmd = lastcmd; /* extra data gathered, ready for the command */
                    524: } /* end nextchar or nextline mode */
                    525: else if(cmd) {
                    526: /* comand supplied directly */
                    527: cmdp = &sdcmds[cmd];
                    528: rc = 1;
                    529: if(cmdp->nextkey | cmdp->nextline) {
                    530: a->nextchar = cmdp->nextkey;
                    531: if(a->nextline = cmdp->nextline) rc = 5;
                    532: a->lastcmd = cmd;
                    533: a->textlen = 0;
                    534: cmd = 0;
                    535: }
                    536: } /* a valid speech command */
                    537: 
                    538: if(cmd) {
                    539: cmdp = &sdcmds[cmd];
                    540: if(input) {
                    541: /* speech command from the keyboard */
                    542: o->rdflag = o->onesymb = 0; /* stop all reading */
                    543: /* interrupt level, defer command */
                    544: o->talkcmd = cmd;
                    545: mmhasten();
                    546: } else {
                    547: /* speech commands block when they come via output characters */
                    548: /* unless said command does not activate any speech */
                    549: while(!keycmd_start(session, cmdp->nonempty))  ;
                    550: keycmd(cmd);
                    551: keycmd_end();
                    552: } /* end input/output test */
                    553: } /* cmd to run */
                    554: } /* xparent test */
                    555: 
                    556: return rc;
                    557: } /* multikey */
                    558: 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.