xref: /386bsd/usr/src/usr.bin/tn3270/ascii/termin.c (revision a2142627)
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