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