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