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 "m4.out" /* output of termcodes.m4 */ 35 #include "state.h" 36 37 #include "../general/globals.h" 38 #include "../ctlr/function.h" 39 #include "../ctlr/inbound.ext" 40 #include "../ctlr/outbound.ext" 41 #include "../telnet.ext" 42 #include "termin.ext" 43 44 #define IsControl(c) (!isprint(c) || (isspace(c) && ((c) != ' '))) 45 46 #define NextState(x) (x->next) 47 48 /* XXX temporary - hard code in the state table */ 49 50 #define MATCH_ANY 0xff /* actually, match any character */ 51 52 #include "astosc.out" 53 54 static char 55 ourBuffer[100], /* where we store stuff */ 56 *ourPHead = ourBuffer, /* first character in buffer */ 57 *ourPTail = ourBuffer; /* where next character goes */ 58 59 static int InControl; 60 static int WaitingForSynch; 61 62 static state 63 *headOfControl = 0; /* where we enter code state table */ 64 65 #define FullChar ((ourPTail+5) >= ourBuffer+sizeof ourBuffer) 66 #define EmptyChar (ourPTail == ourPHead) 67 68 69 /* 70 * init_keyboard() 71 * 72 * Initialize the keyboard variables. 73 */ 74 75 void 76 init_keyboard() 77 { 78 ourPHead = ourPTail = ourBuffer; 79 InControl = 0; 80 WaitingForSynch = 0; 81 } 82 83 84 /* 85 * Initialize the keyboard mapping file. 86 */ 87 88 void 89 InitMapping() 90 { 91 extern state *InitControl(); 92 93 if (!headOfControl) { 94 /* need to initialize */ 95 headOfControl = InitControl((char *)0, 0); 96 if (!headOfControl) { /* should not occur */ 97 quit(); 98 } 99 } 100 } 101 102 103 /* AddChar - put a character in our buffer */ 104 105 static void 106 AddChar(c) 107 int c; 108 { 109 if (!FullChar) { 110 if ((c >= numberof(asctosc)) || (c < 0)) { 111 ExitString(stderr, 112 "Unable to locate function in termout.c, AddChar()\n", 1); 113 /*NOTREACHED*/ 114 } else { 115 switch (asctosc[c].shift) { 116 case cantdo: 117 if (c == ' ') { 118 *ourPTail++ = asctosc[TC_SPACE].scancode; 119 } else { 120 RingBell("Keyboard not capable of function."); 121 } 122 break; 123 case normal: 124 *ourPTail++ = asctosc[c].scancode; 125 break; 126 case shifted: 127 *ourPTail++ = asctosc[TC_MAKE_SHIFT].scancode; 128 *ourPTail++ = asctosc[c].scancode; 129 *ourPTail++ = asctosc[TC_BREAK_SHIFT].scancode; 130 break; 131 case alted: 132 *ourPTail++ = asctosc[TC_MAKE_ALT].scancode; 133 *ourPTail++ = asctosc[c].scancode; 134 *ourPTail++ = asctosc[TC_BREAK_ALT].scancode; 135 break; 136 case shiftalted: 137 *ourPTail++ = asctosc[TC_MAKE_SHIFT].scancode; 138 *ourPTail++ = asctosc[TC_MAKE_ALT].scancode; 139 *ourPTail++ = asctosc[c].scancode; 140 *ourPTail++ = asctosc[TC_BREAK_ALT].scancode; 141 *ourPTail++ = asctosc[TC_BREAK_SHIFT].scancode; 142 break; 143 default: 144 ExitString(stderr, 145 "Illegal 'shift' to AddChar() in termin.c\n", 1); 146 } 147 } 148 } else { 149 RingBell("Typeahead buffer full"); 150 } 151 } 152 153 /* FlushChar - put everything where it belongs */ 154 155 static void 156 FlushChar() 157 { 158 ourPTail = ourBuffer; 159 ourPHead = ourBuffer; 160 } 161 162 int 163 TerminalIn() 164 { 165 /* send data from us to next link in stream */ 166 int count; 167 168 count = 0; 169 170 if (!EmptyChar) { /* send up the link */ 171 count += DataFrom3270(ourPHead, ourPTail-ourPHead); 172 ourPHead += count; 173 if (EmptyChar) { 174 FlushChar(); 175 } 176 } 177 /* return value answers question: "did we do anything useful?" */ 178 return(count? 1:0); 179 } 180 181 int 182 DataFromTerminal(buffer, count) 183 register char *buffer; /* the data read in */ 184 register int count; /* how many bytes in this buffer */ 185 { 186 register state *regControlPointer; 187 register char c; 188 register int result; 189 int origCount; 190 extern int bellwinup; 191 static state *controlPointer; 192 193 if (bellwinup) { 194 BellOff(); 195 } 196 197 origCount = count; 198 199 while (count) { 200 c = *buffer++&0x7f; 201 count--; 202 203 if (!InControl && !IsControl(c)) { 204 AddChar(c); /* add ascii character */ 205 } else { 206 if (!InControl) { /* first character of sequence */ 207 InControl = 1; 208 controlPointer = headOfControl; 209 } 210 /* control pointer points to current position in state table */ 211 for (regControlPointer = controlPointer; ; 212 regControlPointer = NextState(regControlPointer)) { 213 if (!regControlPointer) { /* ran off end */ 214 RingBell("Invalid control sequence"); 215 regControlPointer = headOfControl; 216 InControl = 0; 217 break; 218 } 219 if ((regControlPointer->match == c) /* hit this character */ 220 || (regControlPointer->match == MATCH_ANY)) { 221 result = regControlPointer->result; 222 if (result == TC_GOTO) { 223 regControlPointer = regControlPointer->address; 224 break; /* go to next character */ 225 } 226 if (WaitingForSynch) { 227 if (result == TC_SYNCH) { 228 WaitingForSynch = 0; 229 } else { 230 RingBell("Need to type synch character"); 231 } 232 } 233 else if (result == TC_FLINP) { 234 FlushChar(); /* Don't add FLINP */ 235 } else { 236 if (result == TC_MASTER_RESET) { 237 FlushChar(); 238 } 239 AddChar(result); /* add this code */ 240 } 241 InControl = 0; /* out of control now */ 242 break; 243 } 244 } 245 controlPointer = regControlPointer; /* save state */ 246 } 247 } 248 (void) TerminalIn(); /* try to send data */ 249 return(origCount-count); 250 } 251