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