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