1 /* 2 * Copyright (c) 1988 Regents of the University of California. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms are permitted 6 * provided that this notice is preserved and that due credit is given 7 * to the University of California at Berkeley. The name of the University 8 * may not be used to endorse or promote products derived from this 9 * software without specific prior written permission. This software 10 * is provided ``as is'' without express or implied warranty. 11 */ 12 13 #ifndef lint 14 static char sccsid[] = "@(#)termin.c 3.2 (Berkeley) 03/28/88"; 15 #endif /* not lint */ 16 17 /* this takes characters from the keyboard, and produces 3270 keystroke 18 codes 19 */ 20 21 #include <stdio.h> 22 #include <ctype.h> 23 24 #include "../general/general.h" 25 #include "../ctlr/function.h" 26 #include "../ctlr/inbound.ext" 27 #include "../ctlr/outbound.ext" 28 #include "../telnet.ext" 29 #include "termin.ext" 30 31 #include "../api/astosc.h" 32 #include "state.h" 33 34 #include "../general/globals.h" 35 36 #define IsControl(c) (!isprint(c) || (isspace(c) && ((c) != ' '))) 37 38 #define NextState(x) (x->next) 39 40 /* XXX temporary - hard code in the state table */ 41 42 #define MATCH_ANY 0xff /* actually, match any character */ 43 44 45 static unsigned char 46 ourBuffer[100], /* where we store stuff */ 47 *ourPHead = ourBuffer, /* first character in buffer */ 48 *ourPTail = ourBuffer, /* where next character goes */ 49 *TransPointer = 0; /* For transparent mode data */ 50 51 static int InControl; 52 static int WaitingForSynch; 53 54 static struct astosc 55 *spacePTR = 0; /* Space is hard to enter */ 56 57 static state 58 *headOfControl = 0; /* where we enter code state table */ 59 60 #define FullChar ((ourPTail+5) >= ourBuffer+sizeof ourBuffer) 61 #define EmptyChar (ourPTail == ourPHead) 62 63 64 /* 65 * init_keyboard() 66 * 67 * Initialize the keyboard variables. 68 */ 69 70 void 71 init_keyboard() 72 { 73 ourPHead = ourPTail = ourBuffer; 74 InControl = 0; 75 WaitingForSynch = 0; 76 } 77 78 79 /* 80 * Initialize the keyboard mapping file. 81 */ 82 83 void 84 InitMapping() 85 { 86 extern state *InitControl(); 87 register struct astosc *ptr; 88 89 if (!headOfControl) { 90 /* need to initialize */ 91 headOfControl = InitControl((char *)0, 0, ascii_to_index); 92 if (!headOfControl) { /* should not occur */ 93 quit(); 94 } 95 for (ptr = &astosc[0]; ptr <= &astosc[highestof(astosc)]; ptr++) { 96 if (ptr->function == FCN_SPACE) { 97 spacePTR = ptr; 98 } 99 } 100 } 101 } 102 103 104 /* AddChar - put a function index in our buffer */ 105 106 static void 107 AddChar(c) 108 int c; 109 { 110 if (!FullChar) { 111 *ourPTail++ = c; 112 } else { 113 RingBell("Typeahead buffer full"); 114 } 115 } 116 117 /* FlushChar - put everything where it belongs */ 118 119 static void 120 FlushChar() 121 { 122 ourPTail = ourBuffer; 123 ourPHead = ourBuffer; 124 } 125 126 void 127 TransInput(onoff, mode) 128 int mode; /* Which KIND of transparent input */ 129 int onoff; /* Going in, or coming out */ 130 { 131 if (onoff) { 132 /* Flush pending input */ 133 FlushChar(); 134 TransPointer = ourBuffer; 135 } else { 136 } 137 } 138 139 int 140 TerminalIn() 141 { 142 /* send data from us to next link in stream */ 143 int work = 0; 144 register struct astosc *ptr; 145 146 while (!EmptyChar) { /* send up the link */ 147 if (*ourPHead == ' ') { 148 ptr = spacePTR; 149 } else { 150 ptr = &astosc[*ourPHead]; 151 } 152 if (AcceptKeystroke(ptr->scancode, ptr->shiftstate) == 1) { 153 ourPHead++; 154 work = 1; 155 } else { 156 break; 157 } 158 } 159 160 if (EmptyChar) { 161 FlushChar(); 162 } 163 /* return value answers question: "did we do anything useful?" */ 164 return work; 165 } 166 167 int 168 DataFromTerminal(buffer, count) 169 register char *buffer; /* the data read in */ 170 register int count; /* how many bytes in this buffer */ 171 { 172 register state *regControlPointer; 173 register char c; 174 register int result; 175 int origCount; 176 extern int bellwinup; 177 static state *controlPointer; 178 179 if (TransPointer) { 180 int i; 181 182 if ((count+TransPointer) >= (ourBuffer+sizeof ourBuffer)) { 183 i = ourBuffer+sizeof ourBuffer-TransPointer; 184 } else { 185 i = count; 186 } 187 while (i--) { 188 c = (*buffer++)&0x7f; 189 *TransPointer++ = c|0x80; 190 if (c == '\r') { 191 SendTransparent(ourBuffer, TransPointer-ourBuffer); 192 TransPointer = 0; /* Done */ 193 break; 194 } 195 } 196 return count; 197 } 198 199 if (bellwinup) { 200 BellOff(); 201 } 202 203 origCount = count; 204 205 while (count) { 206 c = *buffer++&0x7f; 207 count--; 208 209 if (!InControl && !IsControl(c)) { 210 AddChar(c); /* add ascii character */ 211 } else { 212 if (!InControl) { /* first character of sequence */ 213 InControl = 1; 214 controlPointer = headOfControl; 215 } 216 /* control pointer points to current position in state table */ 217 for (regControlPointer = controlPointer; ; 218 regControlPointer = NextState(regControlPointer)) { 219 if (!regControlPointer) { /* ran off end */ 220 RingBell("Invalid control sequence"); 221 regControlPointer = headOfControl; 222 InControl = 0; 223 count = 0; /* Flush current input */ 224 break; 225 } 226 if ((regControlPointer->match == c) /* hit this character */ 227 || (regControlPointer->match == MATCH_ANY)) { 228 result = regControlPointer->result; 229 if (result == STATE_GOTO) { 230 regControlPointer = regControlPointer->address; 231 break; /* go to next character */ 232 } 233 if (WaitingForSynch) { 234 if (astosc[result].function == FCN_SYNCH) { 235 WaitingForSynch = 0; 236 } else { 237 RingBell("Need to type synch character"); 238 } 239 } 240 else if (astosc[result].function == FCN_FLINP) { 241 FlushChar(); /* Don't add FLINP */ 242 } else { 243 if (astosc[result].function == FCN_MASTER_RESET) { 244 FlushChar(); 245 } 246 AddChar(result); /* add this code */ 247 } 248 InControl = 0; /* out of control now */ 249 break; 250 } 251 } 252 controlPointer = regControlPointer; /* save state */ 253 } 254 } 255 (void) TerminalIn(); /* try to send data */ 256 return(origCount-count); 257 } 258