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