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