xref: /csrg-svn/usr.bin/tn3270/ascii/termin.c (revision 31446)
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/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 "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 
59 static int InControl;
60 static int WaitingForSynch;
61 
62 static struct astosc
63 	*spacePTR = 0;		/* Space is hard to enter */
64 
65 static state
66 	*headOfControl = 0;	/* where we enter code state table */
67 
68 #define FullChar	((ourPTail+5) >= ourBuffer+sizeof ourBuffer)
69 #define EmptyChar	(ourPTail == ourPHead)
70 
71 
72 /*
73  * init_keyboard()
74  *
75  * Initialize the keyboard variables.
76  */
77 
78 void
79 init_keyboard()
80 {
81     ourPHead = ourPTail = ourBuffer;
82     InControl = 0;
83     WaitingForSynch = 0;
84 }
85 
86 
87 /*
88  * Initialize the keyboard mapping file.
89  */
90 
91 void
92 InitMapping()
93 {
94     extern state *InitControl();
95     register struct astosc *ptr;
96 
97     if (!headOfControl) {
98 	/* need to initialize */
99 	headOfControl = InitControl((char *)0, 0, ascii_to_index);
100 	if (!headOfControl) {		/* should not occur */
101 	    quit();
102 	}
103 	for (ptr = &astosc[0]; ptr <= &astosc[highestof(astosc)]; ptr++) {
104 	    if (ptr->function == FCN_SPACE) {
105 		spacePTR = ptr;
106 	    }
107 	}
108     }
109 }
110 
111 
112 /* AddChar - put a function index in our buffer */
113 
114 static void
115 AddChar(c)
116 int	c;
117 {
118     if (!FullChar) {
119 	*ourPTail++ = c;
120     } else {
121 	RingBell("Typeahead buffer full");
122     }
123 }
124 
125 /* FlushChar - put everything where it belongs */
126 
127 static void
128 FlushChar()
129 {
130     ourPTail = ourBuffer;
131     ourPHead = ourBuffer;
132 }
133 
134 int
135 TerminalIn()
136 {
137     /* send data from us to next link in stream */
138     int work = 0;
139     register struct astosc *ptr;
140 
141     while (!EmptyChar) {			/* send up the link */
142 	if (*ourPHead == ' ') {
143 	    ptr = spacePTR;
144 	} else {
145 	    ptr = &astosc[*ourPHead];
146 	}
147 	if (AcceptKeystroke(ptr->scancode, ptr->shiftstate) == 1) {
148 	    ourPHead++;
149 	    work = 1;
150 	} else {
151 	    break;
152 	}
153     }
154 
155     if (EmptyChar) {
156 	FlushChar();
157     }
158 	/* return value answers question: "did we do anything useful?" */
159     return work;
160 }
161 
162 int
163 DataFromTerminal(buffer, count)
164 register char	*buffer;		/* the data read in */
165 register int	count;			/* how many bytes in this buffer */
166 {
167     register state *regControlPointer;
168     register char c;
169     register int result;
170     int origCount;
171     extern int bellwinup;
172     static state *controlPointer;
173 
174     if (bellwinup) {
175 	BellOff();
176     }
177 
178     origCount = count;
179 
180     while (count) {
181 	c = *buffer++&0x7f;
182 	count--;
183 
184 	if (!InControl && !IsControl(c)) {
185 	    AddChar(c);			/* add ascii character */
186 	} else {
187 	    if (!InControl) {		/* first character of sequence */
188 		InControl = 1;
189 		controlPointer = headOfControl;
190 	    }
191 	    /* control pointer points to current position in state table */
192 	    for (regControlPointer = controlPointer; ;
193 			regControlPointer = NextState(regControlPointer)) {
194 		if (!regControlPointer) {	/* ran off end */
195 		    RingBell("Invalid control sequence");
196 		    regControlPointer = headOfControl;
197 		    InControl = 0;
198 		    break;
199 		}
200 		if ((regControlPointer->match == c) /* hit this character */
201 			|| (regControlPointer->match == MATCH_ANY)) {
202 		    result = regControlPointer->result;
203 		    if (result == STATE_GOTO) {
204 			regControlPointer = regControlPointer->address;
205 			break;			/* go to next character */
206 		    }
207 		    if (WaitingForSynch) {
208 			if (astosc[result].function == FCN_SYNCH) {
209 			    WaitingForSynch = 0;
210 			} else {
211 			    RingBell("Need to type synch character");
212 			}
213 		    }
214 		    else if (astosc[result].function == FCN_FLINP) {
215 			FlushChar();		/* Don't add FLINP */
216 		    } else {
217 			if (astosc[result].function == FCN_MASTER_RESET) {
218 			    FlushChar();
219 			}
220 			AddChar(result);		/* add this code */
221 		    }
222 		    InControl = 0;	/* out of control now */
223 		    break;
224 		}
225 	    }
226 	    controlPointer = regControlPointer;		/* save state */
227 	}
228     }
229     (void) TerminalIn();			/* try to send data */
230     return(origCount-count);
231 }
232