xref: /original-bsd/usr.bin/tn3270/ascii/termin.c (revision 95ecee29)
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
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
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
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
113 FlushChar()
114 {
115     ourPTail = ourBuffer;
116     ourPHead = ourBuffer;
117 }
118 
119 /*ARGSUSED*/
120 void
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
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
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