130330Sminshall /* 2*33817Sbostic * Copyright (c) 1988 Regents of the University of California. 3*33817Sbostic * All rights reserved. 430330Sminshall * 5*33817Sbostic * Redistribution and use in source and binary forms are permitted 6*33817Sbostic * provided that this notice is preserved and that due credit is given 7*33817Sbostic * to the University of California at Berkeley. The name of the University 8*33817Sbostic * may not be used to endorse or promote products derived from this 9*33817Sbostic * software without specific prior written permission. This software 10*33817Sbostic * is provided ``as is'' without express or implied warranty. 1130330Sminshall */ 1230330Sminshall 13*33817Sbostic #ifndef lint 14*33817Sbostic static char sccsid[] = "@(#)termin.c 3.2 (Berkeley) 03/28/88"; 15*33817Sbostic #endif /* not lint */ 1630330Sminshall 1730330Sminshall /* this takes characters from the keyboard, and produces 3270 keystroke 1830330Sminshall codes 1930330Sminshall */ 2030330Sminshall 2130331Sminshall #include <stdio.h> 2230330Sminshall #include <ctype.h> 2330330Sminshall 2431176Sminshall #include "../general/general.h" 2530331Sminshall #include "../ctlr/function.h" 2630331Sminshall #include "../ctlr/inbound.ext" 2730331Sminshall #include "../ctlr/outbound.ext" 2830331Sminshall #include "../telnet.ext" 2930330Sminshall #include "termin.ext" 3030330Sminshall 3131870Sminshall #include "../api/astosc.h" 3231245Sminshall #include "state.h" 3331245Sminshall 3431245Sminshall #include "../general/globals.h" 3531245Sminshall 3630330Sminshall #define IsControl(c) (!isprint(c) || (isspace(c) && ((c) != ' '))) 3730330Sminshall 3830330Sminshall #define NextState(x) (x->next) 3930330Sminshall 4030330Sminshall /* XXX temporary - hard code in the state table */ 4130330Sminshall 4230330Sminshall #define MATCH_ANY 0xff /* actually, match any character */ 4330330Sminshall 4430330Sminshall 4531245Sminshall static unsigned char 4630330Sminshall ourBuffer[100], /* where we store stuff */ 4730330Sminshall *ourPHead = ourBuffer, /* first character in buffer */ 4831865Sminshall *ourPTail = ourBuffer, /* where next character goes */ 4931865Sminshall *TransPointer = 0; /* For transparent mode data */ 5030330Sminshall 5130331Sminshall static int InControl; 5230331Sminshall static int WaitingForSynch; 5330331Sminshall 5431245Sminshall static struct astosc 5531245Sminshall *spacePTR = 0; /* Space is hard to enter */ 5631245Sminshall 5730330Sminshall static state 5830330Sminshall *headOfControl = 0; /* where we enter code state table */ 5930330Sminshall 6030331Sminshall #define FullChar ((ourPTail+5) >= ourBuffer+sizeof ourBuffer) 6130330Sminshall #define EmptyChar (ourPTail == ourPHead) 6230330Sminshall 6330330Sminshall 6430331Sminshall /* 6530725Sminshall * init_keyboard() 6630725Sminshall * 6730725Sminshall * Initialize the keyboard variables. 6830725Sminshall */ 6930725Sminshall 7030725Sminshall void 7130725Sminshall init_keyboard() 7230725Sminshall { 7330725Sminshall ourPHead = ourPTail = ourBuffer; 7430725Sminshall InControl = 0; 7530725Sminshall WaitingForSynch = 0; 7630725Sminshall } 7730725Sminshall 7830725Sminshall 7930725Sminshall /* 8030331Sminshall * Initialize the keyboard mapping file. 8130331Sminshall */ 8230331Sminshall 8330331Sminshall void 8430331Sminshall InitMapping() 8530331Sminshall { 8630331Sminshall extern state *InitControl(); 8731245Sminshall register struct astosc *ptr; 8830331Sminshall 8930331Sminshall if (!headOfControl) { 9030331Sminshall /* need to initialize */ 9131245Sminshall headOfControl = InitControl((char *)0, 0, ascii_to_index); 9230331Sminshall if (!headOfControl) { /* should not occur */ 9330331Sminshall quit(); 9430331Sminshall } 9531245Sminshall for (ptr = &astosc[0]; ptr <= &astosc[highestof(astosc)]; ptr++) { 9631245Sminshall if (ptr->function == FCN_SPACE) { 9731245Sminshall spacePTR = ptr; 9831245Sminshall } 9931245Sminshall } 10030331Sminshall } 10130331Sminshall } 10230331Sminshall 10330331Sminshall 10431245Sminshall /* AddChar - put a function index in our buffer */ 10530330Sminshall 10630330Sminshall static void 10730330Sminshall AddChar(c) 10830330Sminshall int c; 10930330Sminshall { 11030330Sminshall if (!FullChar) { 11131245Sminshall *ourPTail++ = c; 11230330Sminshall } else { 11330331Sminshall RingBell("Typeahead buffer full"); 11430330Sminshall } 11530330Sminshall } 11630330Sminshall 11730330Sminshall /* FlushChar - put everything where it belongs */ 11830330Sminshall 11930330Sminshall static void 12030330Sminshall FlushChar() 12130330Sminshall { 12230330Sminshall ourPTail = ourBuffer; 12330330Sminshall ourPHead = ourBuffer; 12430330Sminshall } 12530330Sminshall 12631865Sminshall void 12731865Sminshall TransInput(onoff, mode) 12831865Sminshall int mode; /* Which KIND of transparent input */ 12931865Sminshall int onoff; /* Going in, or coming out */ 13031865Sminshall { 13131865Sminshall if (onoff) { 13231865Sminshall /* Flush pending input */ 13331865Sminshall FlushChar(); 13431865Sminshall TransPointer = ourBuffer; 13531865Sminshall } else { 13631865Sminshall } 13731865Sminshall } 13831865Sminshall 13930330Sminshall int 14030330Sminshall TerminalIn() 14130330Sminshall { 14230330Sminshall /* send data from us to next link in stream */ 14331245Sminshall int work = 0; 14431245Sminshall register struct astosc *ptr; 14530330Sminshall 14631245Sminshall while (!EmptyChar) { /* send up the link */ 14731446Sminshall if (*ourPHead == ' ') { 14831446Sminshall ptr = spacePTR; 14931446Sminshall } else { 15031446Sminshall ptr = &astosc[*ourPHead]; 15131446Sminshall } 15231245Sminshall if (AcceptKeystroke(ptr->scancode, ptr->shiftstate) == 1) { 15331245Sminshall ourPHead++; 15431245Sminshall work = 1; 15531446Sminshall } else { 15631446Sminshall break; 15730330Sminshall } 15830330Sminshall } 15931446Sminshall 16031245Sminshall if (EmptyChar) { 16131245Sminshall FlushChar(); 16231245Sminshall } 16330330Sminshall /* return value answers question: "did we do anything useful?" */ 16431245Sminshall return work; 16530330Sminshall } 16630330Sminshall 16730330Sminshall int 16830330Sminshall DataFromTerminal(buffer, count) 16930330Sminshall register char *buffer; /* the data read in */ 17030330Sminshall register int count; /* how many bytes in this buffer */ 17130330Sminshall { 17230330Sminshall register state *regControlPointer; 17330330Sminshall register char c; 17430330Sminshall register int result; 17530330Sminshall int origCount; 17630331Sminshall extern int bellwinup; 17730330Sminshall static state *controlPointer; 17830330Sminshall 17931865Sminshall if (TransPointer) { 18031865Sminshall int i; 18131865Sminshall 18231865Sminshall if ((count+TransPointer) >= (ourBuffer+sizeof ourBuffer)) { 18331865Sminshall i = ourBuffer+sizeof ourBuffer-TransPointer; 18431865Sminshall } else { 18531865Sminshall i = count; 18631865Sminshall } 18731865Sminshall while (i--) { 18831966Sminshall c = (*buffer++)&0x7f; 18931865Sminshall *TransPointer++ = c|0x80; 19031865Sminshall if (c == '\r') { 19131865Sminshall SendTransparent(ourBuffer, TransPointer-ourBuffer); 19231865Sminshall TransPointer = 0; /* Done */ 19331865Sminshall break; 19431865Sminshall } 19531865Sminshall } 19631865Sminshall return count; 19731865Sminshall } 19831865Sminshall 19930331Sminshall if (bellwinup) { 20030331Sminshall BellOff(); 20130330Sminshall } 20230330Sminshall 20330330Sminshall origCount = count; 20430330Sminshall 20530330Sminshall while (count) { 20630330Sminshall c = *buffer++&0x7f; 20730330Sminshall count--; 20830330Sminshall 20930330Sminshall if (!InControl && !IsControl(c)) { 21030330Sminshall AddChar(c); /* add ascii character */ 21130330Sminshall } else { 21230330Sminshall if (!InControl) { /* first character of sequence */ 21330330Sminshall InControl = 1; 21430330Sminshall controlPointer = headOfControl; 21530330Sminshall } 21630330Sminshall /* control pointer points to current position in state table */ 21730330Sminshall for (regControlPointer = controlPointer; ; 21830330Sminshall regControlPointer = NextState(regControlPointer)) { 21930330Sminshall if (!regControlPointer) { /* ran off end */ 22030331Sminshall RingBell("Invalid control sequence"); 22130330Sminshall regControlPointer = headOfControl; 22230330Sminshall InControl = 0; 22331447Sminshall count = 0; /* Flush current input */ 22431550Sminshall break; 22530330Sminshall } 22630330Sminshall if ((regControlPointer->match == c) /* hit this character */ 22730330Sminshall || (regControlPointer->match == MATCH_ANY)) { 22830330Sminshall result = regControlPointer->result; 22931245Sminshall if (result == STATE_GOTO) { 23030330Sminshall regControlPointer = regControlPointer->address; 23130330Sminshall break; /* go to next character */ 23230330Sminshall } 23330330Sminshall if (WaitingForSynch) { 23431245Sminshall if (astosc[result].function == FCN_SYNCH) { 23530330Sminshall WaitingForSynch = 0; 23630330Sminshall } else { 23730331Sminshall RingBell("Need to type synch character"); 23830330Sminshall } 23930330Sminshall } 24031245Sminshall else if (astosc[result].function == FCN_FLINP) { 24130330Sminshall FlushChar(); /* Don't add FLINP */ 24230330Sminshall } else { 24331245Sminshall if (astosc[result].function == FCN_MASTER_RESET) { 24430330Sminshall FlushChar(); 24530330Sminshall } 24630330Sminshall AddChar(result); /* add this code */ 24730330Sminshall } 24830330Sminshall InControl = 0; /* out of control now */ 24930330Sminshall break; 25030330Sminshall } 25130330Sminshall } 25230330Sminshall controlPointer = regControlPointer; /* save state */ 25330330Sminshall } 25430330Sminshall } 25530330Sminshall (void) TerminalIn(); /* try to send data */ 25630330Sminshall return(origCount-count); 25730330Sminshall } 258