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