Annotation of coherent/b/kernel/FWB/interfac.c, revision 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.