xref: /csrg-svn/usr.bin/tn3270/ascii/termin.c (revision 30725)
1 /*
2  *	Copyright (c) 1984, 1985, 1986 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	3.1  10/29/86";
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.h"
34 #include "m4.out"		/* output of termcodes.m4 */
35 #include "state.h"
36 
37 #include "../system/globals.h"
38 #include "../ctlr/function.h"
39 #include "../ctlr/inbound.ext"
40 #include "../ctlr/outbound.ext"
41 #include "../telnet.ext"
42 #include "termin.ext"
43 
44 #define IsControl(c)	(!isprint(c) || (isspace(c) && ((c) != ' ')))
45 
46 #define NextState(x)	(x->next)
47 
48 /* XXX temporary - hard code in the state table */
49 
50 #define MATCH_ANY 0xff			/* actually, match any character */
51 
52 #include "astosc.out"
53 
54 static char
55 	ourBuffer[100],		/* where we store stuff */
56 	*ourPHead = ourBuffer,	/* first character in buffer */
57 	*ourPTail = ourBuffer;	/* where next character goes */
58 
59 static int InControl;
60 static int WaitingForSynch;
61 
62 static state
63 	*headOfControl = 0;	/* where we enter code state table */
64 
65 #define FullChar	((ourPTail+5) >= ourBuffer+sizeof ourBuffer)
66 #define EmptyChar	(ourPTail == ourPHead)
67 
68 
69 /*
70  * init_keyboard()
71  *
72  * Initialize the keyboard variables.
73  */
74 
75 void
76 init_keyboard()
77 {
78     ourPHead = ourPTail = ourBuffer;
79     InControl = 0;
80     WaitingForSynch = 0;
81 }
82 
83 
84 /*
85  * Initialize the keyboard mapping file.
86  */
87 
88 void
89 InitMapping()
90 {
91     extern state *InitControl();
92 
93     if (!headOfControl) {
94 	/* need to initialize */
95 	headOfControl = InitControl((char *)0, 0);
96 	if (!headOfControl) {		/* should not occur */
97 	    quit();
98 	}
99     }
100 }
101 
102 
103 /* AddChar - put a character in our buffer */
104 
105 static void
106 AddChar(c)
107 int	c;
108 {
109     if (!FullChar) {
110 	if ((c >= numberof(asctosc)) || (c < 0)) {
111 	    ExitString(stderr,
112 		    "Unable to locate function in termout.c, AddChar()\n", 1);
113 	    /*NOTREACHED*/
114 	} else {
115 	    switch (asctosc[c].shift) {
116 	    case cantdo:
117 		if (c == ' ') {
118 		    *ourPTail++ = asctosc[TC_SPACE].scancode;
119 		} else {
120 		    RingBell("Keyboard not capable of function.");
121 		}
122 		break;
123 	    case normal:
124 		*ourPTail++ = asctosc[c].scancode;
125 		break;
126 	    case shifted:
127 		*ourPTail++ = asctosc[TC_MAKE_SHIFT].scancode;
128 		*ourPTail++ = asctosc[c].scancode;
129 		*ourPTail++ = asctosc[TC_BREAK_SHIFT].scancode;
130 		break;
131 	    case alted:
132 		*ourPTail++ = asctosc[TC_MAKE_ALT].scancode;
133 		*ourPTail++ = asctosc[c].scancode;
134 		*ourPTail++ = asctosc[TC_BREAK_ALT].scancode;
135 		break;
136 	    case shiftalted:
137 		*ourPTail++ = asctosc[TC_MAKE_SHIFT].scancode;
138 		*ourPTail++ = asctosc[TC_MAKE_ALT].scancode;
139 		*ourPTail++ = asctosc[c].scancode;
140 		*ourPTail++ = asctosc[TC_BREAK_ALT].scancode;
141 		*ourPTail++ = asctosc[TC_BREAK_SHIFT].scancode;
142 		break;
143 	    default:
144 		ExitString(stderr,
145 			    "Illegal 'shift' to AddChar() in termin.c\n", 1);
146 	    }
147 	}
148     } else {
149 	RingBell("Typeahead buffer full");
150     }
151 }
152 
153 /* FlushChar - put everything where it belongs */
154 
155 static void
156 FlushChar()
157 {
158     ourPTail = ourBuffer;
159     ourPHead = ourBuffer;
160 }
161 
162 int
163 TerminalIn()
164 {
165     /* send data from us to next link in stream */
166     int count;
167 
168     count = 0;
169 
170     if (!EmptyChar) {			/* send up the link */
171 	count += DataFrom3270(ourPHead, ourPTail-ourPHead);
172 	ourPHead += count;
173 	if (EmptyChar) {
174 	    FlushChar();
175 	}
176     }
177 	/* return value answers question: "did we do anything useful?" */
178     return(count? 1:0);
179 }
180 
181 int
182 DataFromTerminal(buffer, count)
183 register char	*buffer;		/* the data read in */
184 register int	count;			/* how many bytes in this buffer */
185 {
186     register state *regControlPointer;
187     register char c;
188     register int result;
189     int origCount;
190     extern int bellwinup;
191     static state *controlPointer;
192 
193     if (bellwinup) {
194 	BellOff();
195     }
196 
197     origCount = count;
198 
199     while (count) {
200 	c = *buffer++&0x7f;
201 	count--;
202 
203 	if (!InControl && !IsControl(c)) {
204 	    AddChar(c);			/* add ascii character */
205 	} else {
206 	    if (!InControl) {		/* first character of sequence */
207 		InControl = 1;
208 		controlPointer = headOfControl;
209 	    }
210 	    /* control pointer points to current position in state table */
211 	    for (regControlPointer = controlPointer; ;
212 			regControlPointer = NextState(regControlPointer)) {
213 		if (!regControlPointer) {	/* ran off end */
214 		    RingBell("Invalid control sequence");
215 		    regControlPointer = headOfControl;
216 		    InControl = 0;
217 		    break;
218 		}
219 		if ((regControlPointer->match == c) /* hit this character */
220 			|| (regControlPointer->match == MATCH_ANY)) {
221 		    result = regControlPointer->result;
222 		    if (result == TC_GOTO) {
223 			regControlPointer = regControlPointer->address;
224 			break;			/* go to next character */
225 		    }
226 		    if (WaitingForSynch) {
227 			if (result == TC_SYNCH) {
228 			    WaitingForSynch = 0;
229 			} else {
230 			    RingBell("Need to type synch character");
231 			}
232 		    }
233 		    else if (result == TC_FLINP) {
234 			FlushChar();		/* Don't add FLINP */
235 		    } else {
236 			if (result == TC_MASTER_RESET) {
237 			    FlushChar();
238 			}
239 			AddChar(result);		/* add this code */
240 		    }
241 		    InControl = 0;	/* out of control now */
242 		    break;
243 		}
244 	    }
245 	    controlPointer = regControlPointer;		/* save state */
246 	}
247     }
248     (void) TerminalIn();			/* try to send data */
249     return(origCount-count);
250 }
251