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