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