xref: /csrg-svn/usr.bin/tn3270/ctlr/inbound.c (revision 30015)
1*30015Sminshall /*
2*30015Sminshall  *	Copyright (c) 1984, 1985, 1986 by the Regents of the
3*30015Sminshall  *	University of California and by Gregory Glenn Minshall.
4*30015Sminshall  *
5*30015Sminshall  *	Permission to use, copy, modify, and distribute these
6*30015Sminshall  *	programs and their documentation for any purpose and
7*30015Sminshall  *	without fee is hereby granted, provided that this
8*30015Sminshall  *	copyright and permission appear on all copies and
9*30015Sminshall  *	supporting documentation, the name of the Regents of
10*30015Sminshall  *	the University of California not be used in advertising
11*30015Sminshall  *	or publicity pertaining to distribution of the programs
12*30015Sminshall  *	without specific prior permission, and notice be given in
13*30015Sminshall  *	supporting documentation that copying and distribution is
14*30015Sminshall  *	by permission of the Regents of the University of California
15*30015Sminshall  *	and by Gregory Glenn Minshall.  Neither the Regents of the
16*30015Sminshall  *	University of California nor Gregory Glenn Minshall make
17*30015Sminshall  *	representations about the suitability of this software
18*30015Sminshall  *	for any purpose.  It is provided "as is" without
19*30015Sminshall  *	express or implied warranty.
20*30015Sminshall  */
21*30015Sminshall 
22*30015Sminshall 
23*30015Sminshall #ifndef	lint
24*30015Sminshall static	char	sccsid[] = "@(#)inbound.c	3.1  10/29/86";
25*30015Sminshall #endif	/* ndef lint */
26*30015Sminshall 
27*30015Sminshall 
28*30015Sminshall #include <stdio.h>
29*30015Sminshall 
30*30015Sminshall #include "../general.h"
31*30015Sminshall #include "function.h"
32*30015Sminshall #include "hostctlr.h"
33*30015Sminshall #include "scrnctlr.h"
34*30015Sminshall #include "screen.h"
35*30015Sminshall #include "options.h"
36*30015Sminshall #include "dctype.h"
37*30015Sminshall #include "ebc_disp.h"
38*30015Sminshall 
39*30015Sminshall #include "../system/globals.h"
40*30015Sminshall #include "inbound.ext"
41*30015Sminshall #include "outbound.ext"
42*30015Sminshall #include "../telnet.ext"
43*30015Sminshall 
44*30015Sminshall #define EmptyChar()	(ourPTail == ourPHead)
45*30015Sminshall #define FullChar()	(ourPHead == ourBuffer+sizeof ourBuffer)
46*30015Sminshall 
47*30015Sminshall 
48*30015Sminshall /*
49*30015Sminshall  * We define something to allow us to to IsProtected() quickly
50*30015Sminshall  * on unformatted screens (with the current algorithm for fields,
51*30015Sminshall  * unprotected takes exponential time...).
52*30015Sminshall  *
53*30015Sminshall  *	The idea is to call SetXIsProtected() BEFORE the
54*30015Sminshall  * loop, then use XIsProtected().
55*30015Sminshall  */
56*30015Sminshall 
57*30015Sminshall #define	SetXIsProtected()	XFormattedScreen = FormattedScreen()
58*30015Sminshall #define	XIsProtected(p)		(XFormattedScreen && IsProtected(p))
59*30015Sminshall 
60*30015Sminshall static char	ourBuffer[400];
61*30015Sminshall 
62*30015Sminshall static char	*ourPHead = ourBuffer,
63*30015Sminshall 		*ourPTail = ourBuffer;
64*30015Sminshall 
65*30015Sminshall static int	HadAid = 0;		/* Had an AID haven't sent */
66*30015Sminshall 
67*30015Sminshall static int	XFormattedScreen = 0;	/* For optimizations */
68*30015Sminshall 
69*30015Sminshall #include "3270pc.out"
70*30015Sminshall 
71*30015Sminshall /* the following are global variables */
72*30015Sminshall 
73*30015Sminshall extern int UnLocked;		/* keyboard is UnLocked? */
74*30015Sminshall 
75*30015Sminshall /* Tab() - sets cursor to the start of the next unprotected field */
76*30015Sminshall static void
77*30015Sminshall Tab()
78*30015Sminshall {
79*30015Sminshall     register int i, j;
80*30015Sminshall 
81*30015Sminshall     i = CursorAddress;
82*30015Sminshall     j = WhereAttrByte(CursorAddress);
83*30015Sminshall     do {
84*30015Sminshall 	if (IsStartField(i) && IsUnProtected(ScreenInc(i))) {
85*30015Sminshall 	    break;
86*30015Sminshall 	}
87*30015Sminshall 	i = FieldInc(i);
88*30015Sminshall     } while (i != j);
89*30015Sminshall     if (IsStartField(i) && IsUnProtected(ScreenInc(i))) {
90*30015Sminshall 	CursorAddress = ScreenInc(i);
91*30015Sminshall     } else {
92*30015Sminshall 	CursorAddress = SetBufferAddress(0,0);
93*30015Sminshall     }
94*30015Sminshall }
95*30015Sminshall 
96*30015Sminshall 
97*30015Sminshall /* BackTab() - sets cursor to the start of the most recent field */
98*30015Sminshall 
99*30015Sminshall static void
100*30015Sminshall BackTab()
101*30015Sminshall {
102*30015Sminshall     register int i;
103*30015Sminshall 
104*30015Sminshall     i = ScreenDec(CursorAddress);
105*30015Sminshall     for (;;) {
106*30015Sminshall 	if (IsStartField(ScreenDec(i)) && IsUnProtected(i)) {
107*30015Sminshall 	    CursorAddress = i;
108*30015Sminshall 	    break;
109*30015Sminshall 	}
110*30015Sminshall 	if (i == CursorAddress) {
111*30015Sminshall 	    CursorAddress = SetBufferAddress(0,0);
112*30015Sminshall 	    break;
113*30015Sminshall 	}
114*30015Sminshall 	i = ScreenDec(i);
115*30015Sminshall     }
116*30015Sminshall }
117*30015Sminshall 
118*30015Sminshall 
119*30015Sminshall /* EraseEndOfField - erase all characters to the end of a field */
120*30015Sminshall 
121*30015Sminshall static void
122*30015Sminshall EraseEndOfField()
123*30015Sminshall {
124*30015Sminshall     register int i;
125*30015Sminshall 
126*30015Sminshall     if (IsProtected(CursorAddress)) {
127*30015Sminshall 	RingBell("Protected Field");
128*30015Sminshall     } else {
129*30015Sminshall 	TurnOnMdt(CursorAddress);
130*30015Sminshall 	if (FormattedScreen()) {
131*30015Sminshall 	    i = CursorAddress;
132*30015Sminshall 	    do {
133*30015Sminshall 		AddHost(i, 0);
134*30015Sminshall 		i = ScreenInc(i);
135*30015Sminshall 	    } while ((i != CursorAddress) && !IsStartField(i));
136*30015Sminshall 	} else {                            /* Screen is Unformatted */
137*30015Sminshall 	    i = CursorAddress;
138*30015Sminshall 	    do {
139*30015Sminshall 		AddHost(i, 0);
140*30015Sminshall 		i = ScreenInc(i);
141*30015Sminshall 	    } while (i != HighestScreen());
142*30015Sminshall        }
143*30015Sminshall     }
144*30015Sminshall }
145*30015Sminshall 
146*30015Sminshall /* Delete() - deletes a character from the screen
147*30015Sminshall  *
148*30015Sminshall  *	What we want to do is delete the section
149*30015Sminshall  *	[where, from-1] from the screen,
150*30015Sminshall  *	filling in with what comes at from.
151*30015Sminshall  *
152*30015Sminshall  *	The deleting continues to the end of the field (or
153*30015Sminshall  *	until the cursor wraps).
154*30015Sminshall  *
155*30015Sminshall  *	From can be a start of a field.  We
156*30015Sminshall  *	check for that.  However, there can't be any
157*30015Sminshall  *	fields that start between where and from.
158*30015Sminshall  *	We don't check for that.
159*30015Sminshall  *
160*30015Sminshall  *	Also, we assume that the protection status of
161*30015Sminshall  *	everything has been checked by the caller.
162*30015Sminshall  *
163*30015Sminshall  */
164*30015Sminshall 
165*30015Sminshall static void
166*30015Sminshall Delete(where, from)
167*30015Sminshall register int	where,		/* Where to start deleting from */
168*30015Sminshall 		from;		/* Where to pull back from */
169*30015Sminshall {
170*30015Sminshall     register int i;
171*30015Sminshall 
172*30015Sminshall     TurnOnMdt(where);			/* Only do this once in this field */
173*30015Sminshall     i = where;
174*30015Sminshall     do {
175*30015Sminshall 	if (IsStartField(from)) {
176*30015Sminshall 	    AddHost(i, 0);		/* Stick the edge at the start field */
177*30015Sminshall 	} else {
178*30015Sminshall 	    AddHost(i, GetHost(from));
179*30015Sminshall 	    from = ScreenInc(from);		/* Move the edge */
180*30015Sminshall 	}
181*30015Sminshall 	i = ScreenInc(i);
182*30015Sminshall     } while ((!IsStartField(i)) && (i != where));
183*30015Sminshall }
184*30015Sminshall 
185*30015Sminshall static void
186*30015Sminshall ColBak()
187*30015Sminshall {
188*30015Sminshall     register int i;
189*30015Sminshall 
190*30015Sminshall     i = ScreenLineOffset(CursorAddress);
191*30015Sminshall     for (i = i-1; i >= 0; i--) {
192*30015Sminshall 	if (OptColTabs[i]) {
193*30015Sminshall 	    break;
194*30015Sminshall 	}
195*30015Sminshall     }
196*30015Sminshall     if (i < 0) {
197*30015Sminshall 	i = 0;
198*30015Sminshall     }
199*30015Sminshall     CursorAddress = SetBufferAddress(ScreenLine(CursorAddress), i);
200*30015Sminshall }
201*30015Sminshall 
202*30015Sminshall static void
203*30015Sminshall ColTab()
204*30015Sminshall {
205*30015Sminshall     register int i;
206*30015Sminshall 
207*30015Sminshall     i = ScreenLineOffset(CursorAddress);
208*30015Sminshall     for (i = i+1; i < NumberColumns; i++) {
209*30015Sminshall 	if (OptColTabs[i]) {
210*30015Sminshall 	    break;
211*30015Sminshall 	}
212*30015Sminshall     }
213*30015Sminshall     if (i >= NumberColumns) {
214*30015Sminshall 	i = NumberColumns-1;
215*30015Sminshall     }
216*30015Sminshall     CursorAddress = SetBufferAddress(ScreenLine(CursorAddress), i);
217*30015Sminshall }
218*30015Sminshall 
219*30015Sminshall static void
220*30015Sminshall Home()
221*30015Sminshall {
222*30015Sminshall     register int i;
223*30015Sminshall     register int j;
224*30015Sminshall 
225*30015Sminshall     i = SetBufferAddress(OptHome, 0);
226*30015Sminshall     j = WhereLowByte(i);
227*30015Sminshall     do {
228*30015Sminshall 	if (IsUnProtected(i)) {
229*30015Sminshall 	    CursorAddress = i;
230*30015Sminshall 	    return;
231*30015Sminshall 	}
232*30015Sminshall 	    /* the following could be a problem if we got here with an
233*30015Sminshall 	     * unformatted screen.  However, this is "impossible", since
234*30015Sminshall 	     * with an unformatted screen, the IsUnProtected(i) above
235*30015Sminshall 	     * should be true.
236*30015Sminshall 	     */
237*30015Sminshall 	i = ScreenInc(FieldInc(i));
238*30015Sminshall     } while (i != j);
239*30015Sminshall     CursorAddress = LowestScreen();
240*30015Sminshall }
241*30015Sminshall 
242*30015Sminshall static
243*30015Sminshall LastOfField(i)
244*30015Sminshall register int	i;	/* position to start from */
245*30015Sminshall {
246*30015Sminshall     register int j;
247*30015Sminshall     register int k;
248*30015Sminshall 
249*30015Sminshall     k = j = i;
250*30015Sminshall     SetXIsProtected();
251*30015Sminshall     while (XIsProtected(i) || Disspace(GetHost(i))) {
252*30015Sminshall 	i = ScreenInc(i);
253*30015Sminshall 	if (i == j) {
254*30015Sminshall 	    break;
255*30015Sminshall 	}
256*30015Sminshall     }
257*30015Sminshall 	    /* We are now IN a word IN an unprotected field (or wrapped) */
258*30015Sminshall     while (!XIsProtected(i)) {
259*30015Sminshall 	if (!Disspace(GetHost(i))) {
260*30015Sminshall 	    k = i;
261*30015Sminshall 	}
262*30015Sminshall 	i = ScreenInc(i);
263*30015Sminshall 	if (i == j) {
264*30015Sminshall 	    break;
265*30015Sminshall 	}
266*30015Sminshall     }
267*30015Sminshall     return(k);
268*30015Sminshall }
269*30015Sminshall 
270*30015Sminshall 
271*30015Sminshall static void
272*30015Sminshall FlushChar()
273*30015Sminshall {
274*30015Sminshall     ourPTail = ourPHead = ourBuffer;
275*30015Sminshall }
276*30015Sminshall 
277*30015Sminshall 
278*30015Sminshall /*
279*30015Sminshall  * Add one EBCDIC (NOT display code) character to the buffer.
280*30015Sminshall  */
281*30015Sminshall 
282*30015Sminshall static void
283*30015Sminshall AddChar(character)
284*30015Sminshall char	character;
285*30015Sminshall {
286*30015Sminshall     if (FullChar()) {
287*30015Sminshall 	ourPTail += DataToNetwork(ourPTail, ourPHead-ourPTail, 0);
288*30015Sminshall 	if (EmptyChar()) {
289*30015Sminshall 	    FlushChar();
290*30015Sminshall 	} else {
291*30015Sminshall 	    fprintf(stderr, "File %s, line %d:  No room in network buffer!\n",
292*30015Sminshall 				__FILE__, __LINE__);
293*30015Sminshall 	    return;
294*30015Sminshall 	}
295*30015Sminshall     }
296*30015Sminshall     *ourPHead++ = character;
297*30015Sminshall }
298*30015Sminshall 
299*30015Sminshall 
300*30015Sminshall static void
301*30015Sminshall SendUnformatted()
302*30015Sminshall {
303*30015Sminshall     register int i, j;
304*30015Sminshall     register int Nulls;
305*30015Sminshall     register int c;
306*30015Sminshall 
307*30015Sminshall 			/* look for start of field */
308*30015Sminshall     Nulls = 0;
309*30015Sminshall     i = j = LowestScreen();
310*30015Sminshall     do {
311*30015Sminshall 	c = GetHost(i);
312*30015Sminshall 	if (c == 0) {
313*30015Sminshall 	    Nulls++;
314*30015Sminshall 	} else {
315*30015Sminshall 	    while (Nulls) {
316*30015Sminshall 		Nulls--;
317*30015Sminshall 		AddChar(EBCDIC_BLANK);		/* put in blanks */
318*30015Sminshall 	    }
319*30015Sminshall 	    AddChar(disp_ebc[c]);
320*30015Sminshall 	}
321*30015Sminshall 	i = ScreenInc(i);
322*30015Sminshall     } while (i != j);
323*30015Sminshall }
324*30015Sminshall 
325*30015Sminshall static
326*30015Sminshall SendField(i, command)
327*30015Sminshall register int i;			/* where we saw MDT bit */
328*30015Sminshall int	command;		/* The command code (type of read) */
329*30015Sminshall {
330*30015Sminshall     register int j;
331*30015Sminshall     register int k;
332*30015Sminshall     register int Nulls;
333*30015Sminshall     register int c;
334*30015Sminshall 
335*30015Sminshall 			/* look for start of field */
336*30015Sminshall     i = j = WhereLowByte(i);
337*30015Sminshall 
338*30015Sminshall 		/* On a test_request_read, don't send sba and address */
339*30015Sminshall     if ((AidByte != AID_TREQ)
340*30015Sminshall 			|| (command == CMD_SNA_READ_MODIFIED_ALL)) {
341*30015Sminshall 	AddChar(ORDER_SBA);		/* set start field */
342*30015Sminshall 	AddChar(BufferTo3270_0(j));	/* set address of this field */
343*30015Sminshall 	AddChar(BufferTo3270_1(j));
344*30015Sminshall     }
345*30015Sminshall 		/*
346*30015Sminshall 		 * Only on read_modified_all do we return the contents
347*30015Sminshall 		 * of the field when the attention was caused by a
348*30015Sminshall 		 * selector pen.
349*30015Sminshall 		 */
350*30015Sminshall     if ((AidByte != AID_SELPEN)
351*30015Sminshall 			|| (command == CMD_SNA_READ_MODIFIED_ALL)) {
352*30015Sminshall 	if (!IsStartField(j)) {
353*30015Sminshall 	    Nulls = 0;
354*30015Sminshall 	    k = ScreenInc(WhereHighByte(j));
355*30015Sminshall 	    do {
356*30015Sminshall 		c = GetHost(j);
357*30015Sminshall 		if (c == 0) {
358*30015Sminshall 		    Nulls++;
359*30015Sminshall 		} else {
360*30015Sminshall 		    while (Nulls) {
361*30015Sminshall 			Nulls--;
362*30015Sminshall 			AddChar(EBCDIC_BLANK);		/* put in blanks */
363*30015Sminshall 		    }
364*30015Sminshall 		    AddChar(disp_ebc[c]);
365*30015Sminshall 		}
366*30015Sminshall 		j = ScreenInc(j);
367*30015Sminshall 	    } while ((j != k) && (j != i));
368*30015Sminshall 	}
369*30015Sminshall     } else {
370*30015Sminshall 	j = FieldInc(j);
371*30015Sminshall     }
372*30015Sminshall     return(j);
373*30015Sminshall }
374*30015Sminshall 
375*30015Sminshall /* Various types of reads... */
376*30015Sminshall void
377*30015Sminshall DoReadModified(command)
378*30015Sminshall int	command;			/* The command sent */
379*30015Sminshall {
380*30015Sminshall     register int i, j;
381*30015Sminshall 
382*30015Sminshall     if (AidByte) {
383*30015Sminshall 	if (AidByte != AID_TREQ) {
384*30015Sminshall 	    AddChar(AidByte);
385*30015Sminshall 	} else {
386*30015Sminshall 		/* Test Request Read header */
387*30015Sminshall 	    AddChar(EBCDIC_SOH);
388*30015Sminshall 	    AddChar(EBCDIC_PERCENT);
389*30015Sminshall 	    AddChar(EBCDIC_SLASH);
390*30015Sminshall 	    AddChar(EBCDIC_STX);
391*30015Sminshall 	}
392*30015Sminshall     } else {
393*30015Sminshall 	AddChar(AID_NONE);
394*30015Sminshall     }
395*30015Sminshall     if (((AidByte != AID_PA1) && (AidByte != AID_PA2)
396*30015Sminshall 	    && (AidByte != AID_PA3) && (AidByte != AID_CLEAR))
397*30015Sminshall 	    || (command == CMD_SNA_READ_MODIFIED_ALL)) {
398*30015Sminshall 	if ((AidByte != AID_TREQ)
399*30015Sminshall 	    || (command == CMD_SNA_READ_MODIFIED_ALL)) {
400*30015Sminshall 		/* Test request read_modified doesn't give cursor address */
401*30015Sminshall 	    AddChar(BufferTo3270_0(CursorAddress));
402*30015Sminshall 	    AddChar(BufferTo3270_1(CursorAddress));
403*30015Sminshall 	}
404*30015Sminshall 	i = j = WhereAttrByte(LowestScreen());
405*30015Sminshall 	/* Is this an unformatted screen? */
406*30015Sminshall 	if (!IsStartField(i)) {		/* yes, handle separate */
407*30015Sminshall 	    SendUnformatted();
408*30015Sminshall 	} else {
409*30015Sminshall 	    do {
410*30015Sminshall 		if (HasMdt(i)) {
411*30015Sminshall 		    i = SendField(i, command);
412*30015Sminshall 		} else {
413*30015Sminshall 		    i = FieldInc(i);
414*30015Sminshall 		}
415*30015Sminshall 	    } while (i != j);
416*30015Sminshall 	}
417*30015Sminshall     }
418*30015Sminshall     ourPTail += DataToNetwork(ourPTail, ourPHead-ourPTail, 1);
419*30015Sminshall     if (EmptyChar()) {
420*30015Sminshall 	FlushChar();
421*30015Sminshall 	HadAid = 0;			/* killed that buffer */
422*30015Sminshall     }
423*30015Sminshall }
424*30015Sminshall 
425*30015Sminshall /* A read buffer operation... */
426*30015Sminshall 
427*30015Sminshall void
428*30015Sminshall DoReadBuffer()
429*30015Sminshall {
430*30015Sminshall     register int i, j;
431*30015Sminshall 
432*30015Sminshall     if (AidByte) {
433*30015Sminshall 	AddChar(AidByte);
434*30015Sminshall     } else {
435*30015Sminshall 	AddChar(AID_NONE);
436*30015Sminshall     }
437*30015Sminshall     AddChar(BufferTo3270_0(CursorAddress));
438*30015Sminshall     AddChar(BufferTo3270_1(CursorAddress));
439*30015Sminshall     i = j = LowestScreen();
440*30015Sminshall     do {
441*30015Sminshall 	if (IsStartField(i)) {
442*30015Sminshall 	    AddChar(ORDER_SF);
443*30015Sminshall 	    AddChar(BufferTo3270_1(FieldAttributes(i)));
444*30015Sminshall 	} else {
445*30015Sminshall 	    AddChar(disp_ebc[GetHost(i)]);
446*30015Sminshall 	}
447*30015Sminshall 	i = ScreenInc(i);
448*30015Sminshall     } while (i != j);
449*30015Sminshall     ourPTail += DataToNetwork(ourPTail, ourPHead-ourPTail, 1);
450*30015Sminshall     if (EmptyChar()) {
451*30015Sminshall 	FlushChar();
452*30015Sminshall 	HadAid = 0;			/* killed that buffer */
453*30015Sminshall     }
454*30015Sminshall }
455*30015Sminshall /* Try to send some data to host */
456*30015Sminshall 
457*30015Sminshall void
458*30015Sminshall SendToIBM()
459*30015Sminshall {
460*30015Sminshall     extern int TransparentClock, OutputClock;
461*30015Sminshall 
462*30015Sminshall     if (TransparentClock == OutputClock) {
463*30015Sminshall 	if (HadAid) {
464*30015Sminshall 	    AddChar(AidByte);
465*30015Sminshall 	    HadAid = 0;
466*30015Sminshall 	} else {
467*30015Sminshall 	    AddChar(AID_NONE_PRINTER);
468*30015Sminshall 	}
469*30015Sminshall 	do {
470*30015Sminshall 	    ourPTail += DataToNetwork(ourPTail, ourPHead-ourPTail, 1);
471*30015Sminshall 	} while (!EmptyChar());
472*30015Sminshall 	FlushChar();
473*30015Sminshall     } else if (HadAid) {
474*30015Sminshall 	DoReadModified(CMD_READ_MODIFIED);
475*30015Sminshall     }
476*30015Sminshall     netflush();
477*30015Sminshall }
478*30015Sminshall 
479*30015Sminshall /* This takes in one character from the keyboard and places it on the
480*30015Sminshall  * screen.
481*30015Sminshall  */
482*30015Sminshall 
483*30015Sminshall static void
484*30015Sminshall OneCharacter(c, insert)
485*30015Sminshall int c;			/* character (Ebcdic) to be shoved in */
486*30015Sminshall int insert;		/* are we in insert mode? */
487*30015Sminshall {
488*30015Sminshall     register int i, j;
489*30015Sminshall 
490*30015Sminshall     if (IsProtected(CursorAddress)) {
491*30015Sminshall 	RingBell("Protected Field");
492*30015Sminshall 	return;
493*30015Sminshall     }
494*30015Sminshall     if (insert) {
495*30015Sminshall 	/* is the last character in the field a blank or null? */
496*30015Sminshall 	i = ScreenDec(FieldInc(CursorAddress));
497*30015Sminshall 	j = GetHost(i);
498*30015Sminshall 	if (!Disspace(j)) {
499*30015Sminshall 	    RingBell("No more room for insert");
500*30015Sminshall 	    return;
501*30015Sminshall 	} else {
502*30015Sminshall 	    for (j = ScreenDec(i); i != CursorAddress;
503*30015Sminshall 			    j = ScreenDec(j), i = ScreenDec(i)) {
504*30015Sminshall 		AddHost(i, GetHost(j));
505*30015Sminshall 	    }
506*30015Sminshall 	}
507*30015Sminshall     }
508*30015Sminshall     AddHost(CursorAddress, c);
509*30015Sminshall     TurnOnMdt(CursorAddress);
510*30015Sminshall     CursorAddress = ScreenInc(CursorAddress);
511*30015Sminshall     if (IsStartField(CursorAddress) &&
512*30015Sminshall 		((FieldAttributes(CursorAddress)&ATTR_AUTO_SKIP_MASK) ==
513*30015Sminshall 							ATTR_AUTO_SKIP_VALUE)) {
514*30015Sminshall 	Tab();
515*30015Sminshall     }
516*30015Sminshall }
517*30015Sminshall 
518*30015Sminshall /* go through data until an AID character is hit, then generate an interrupt */
519*30015Sminshall 
520*30015Sminshall int
521*30015Sminshall DataFrom3270(buffer, count)
522*30015Sminshall unsigned char	*buffer;		/* where the data is */
523*30015Sminshall int	count;				/* how much data there is */
524*30015Sminshall {
525*30015Sminshall     int origCount;
526*30015Sminshall     register int c;
527*30015Sminshall     register int i;
528*30015Sminshall     register int j;
529*30015Sminshall     static int InsertMode = 0;	/* is the terminal in insert mode? */
530*30015Sminshall     enum type type;
531*30015Sminshall     extern int OutputClock, TransparentClock;
532*30015Sminshall     extern int bellwinup;
533*30015Sminshall     static int shifted = 0, alted = 0;
534*30015Sminshall #   define HITNUM() ((shifted? 1:0) + ((alted?1:0)<<1))
535*30015Sminshall 
536*30015Sminshall     if (bellwinup) {
537*30015Sminshall 	BellOff();
538*30015Sminshall     }
539*30015Sminshall 
540*30015Sminshall     if (*buffer >= numberof(hits)) {
541*30015Sminshall 	ExitString(stderr,
542*30015Sminshall 			"Unknown scancode encountered in DataFrom3270.\n", 1);
543*30015Sminshall 	/*NOTREACHED*/
544*30015Sminshall     }
545*30015Sminshall     type = hits[*buffer].hit[HITNUM()].type;
546*30015Sminshall     c = hits[*buffer].hit[HITNUM()].code;
547*30015Sminshall 
548*30015Sminshall     if (!UnLocked || HadAid) {
549*30015Sminshall 	if (HadAid) {
550*30015Sminshall 	    SendToIBM();
551*30015Sminshall 	    if (!EmptyChar()) {
552*30015Sminshall 		return(0);			/* nothing to do */
553*30015Sminshall 	    }
554*30015Sminshall 	}
555*30015Sminshall 	if (!HadAid && EmptyChar()) {
556*30015Sminshall 	    if ((type == function) && ((c == FCN_RESET) ||
557*30015Sminshall 			(c == FCN_MASTER_RESET))) {
558*30015Sminshall 		UnLocked = 1;
559*30015Sminshall 	    }
560*30015Sminshall 	}
561*30015Sminshall 	if (!UnLocked) {
562*30015Sminshall 	    return(0);
563*30015Sminshall 	}
564*30015Sminshall     }
565*30015Sminshall     /* now, either empty, or haven't seen aid yet */
566*30015Sminshall 
567*30015Sminshall     origCount = count;
568*30015Sminshall 
569*30015Sminshall     if (TransparentClock == OutputClock) {
570*30015Sminshall 	while (count) {
571*30015Sminshall 	    if (*buffer >= numberof(hits)) {
572*30015Sminshall 		ExitString(stderr,
573*30015Sminshall 			"Unknown scancode encountered in DataFrom3270.\n", 1);
574*30015Sminshall 		/*NOTREACHED*/
575*30015Sminshall 	    }
576*30015Sminshall 	    type = hits[*buffer].hit[HITNUM()].type;
577*30015Sminshall 	    c = hits[*buffer].hit[HITNUM()].code;
578*30015Sminshall 	    buffer++;
579*30015Sminshall 	    count--;
580*30015Sminshall 	    if (type == aid) {
581*30015Sminshall 		UnLocked = 0;
582*30015Sminshall 		InsertMode = 0;
583*30015Sminshall 		AidByte = (c);
584*30015Sminshall 		HadAid = 1;
585*30015Sminshall 	    } else if (type == function) {
586*30015Sminshall 		switch (c) {
587*30015Sminshall 		case FCN_ESCAPE:
588*30015Sminshall 		    StopScreen(1);
589*30015Sminshall 		    command(0);
590*30015Sminshall 		    ConnectScreen();
591*30015Sminshall 		    break;
592*30015Sminshall 
593*30015Sminshall 		case FCN_RESET:
594*30015Sminshall 		case FCN_MASTER_RESET:
595*30015Sminshall 		    UnLocked = 1;
596*30015Sminshall 		    break;
597*30015Sminshall 
598*30015Sminshall 		default:
599*30015Sminshall 		    return(origCount-(count+1));
600*30015Sminshall 		}
601*30015Sminshall 	    }
602*30015Sminshall 	}
603*30015Sminshall     }
604*30015Sminshall 
605*30015Sminshall     while (count) {
606*30015Sminshall 	if (*buffer >= numberof(hits)) {
607*30015Sminshall 	    ExitString(stderr,
608*30015Sminshall 			"Unknown scancode encountered in DataFrom3270.\n", 1);
609*30015Sminshall 	    /*NOTREACHED*/
610*30015Sminshall 	}
611*30015Sminshall 	type = hits[*buffer].hit[HITNUM()].type;
612*30015Sminshall 	c = hits[*buffer].hit[HITNUM()].code;
613*30015Sminshall 	buffer++;
614*30015Sminshall 	count--;
615*30015Sminshall 
616*30015Sminshall 	if (type == character) {
617*30015Sminshall 			/* Add the character to the buffer */
618*30015Sminshall 	    OneCharacter(c, InsertMode);
619*30015Sminshall 	} else if (type == aid) {		/* got Aid */
620*30015Sminshall 	    if (c == AID_CLEAR) {
621*30015Sminshall 		LocalClearScreen();	/* Side effect is to clear 3270 */
622*30015Sminshall 	    }
623*30015Sminshall 	    UnLocked = 0;
624*30015Sminshall 	    InsertMode = 0;		/* just like a 3278 */
625*30015Sminshall 	    AidByte = c;
626*30015Sminshall 	    HadAid = 1;
627*30015Sminshall 	    SendToIBM();
628*30015Sminshall 	    return(origCount-count);
629*30015Sminshall 	} else if (type != function) {
630*30015Sminshall 	    ExitString(stderr, "Illegal or undefined scancode!\n", 1);
631*30015Sminshall 	    /*NOTREACHED*/
632*30015Sminshall 	} else {
633*30015Sminshall 	    switch (c) {
634*30015Sminshall 
635*30015Sminshall 	    case FCN_MAKE_SHIFT:
636*30015Sminshall 		shifted++;
637*30015Sminshall 		break;
638*30015Sminshall 	    case FCN_BREAK_SHIFT:
639*30015Sminshall 		shifted--;
640*30015Sminshall 		if (shifted < 0) {
641*30015Sminshall 		    ExitString(stderr,
642*30015Sminshall 				"More BREAK_SHIFT than MAKE_SHIFT.\n", 1);
643*30015Sminshall 		    /*NOTREACHED*/
644*30015Sminshall 		}
645*30015Sminshall 		break;
646*30015Sminshall 	    case FCN_MAKE_ALT:
647*30015Sminshall 		alted++;
648*30015Sminshall 		break;
649*30015Sminshall 	    case FCN_BREAK_ALT:
650*30015Sminshall 		alted--;
651*30015Sminshall 		if (alted < 0) {
652*30015Sminshall 		    ExitString(stderr, "More BREAK_ALT than MAKE_ALT.\n", 1);
653*30015Sminshall 		    /*NOTREACHED*/
654*30015Sminshall 		}
655*30015Sminshall 		break;
656*30015Sminshall 	    case FCN_CURSEL:
657*30015Sminshall 		c = FieldAttributes(CursorAddress)&ATTR_DSPD_MASK;
658*30015Sminshall 		if (!FormattedScreen()
659*30015Sminshall 			|| ((c != ATTR_DSPD_DSPD) && (c != ATTR_DSPD_HIGH))) {
660*30015Sminshall 		    RingBell("Cursor not in selectable field");
661*30015Sminshall 		} else {
662*30015Sminshall 		    i = ScreenInc(WhereAttrByte(CursorAddress));
663*30015Sminshall 		    c = GetHost(i);
664*30015Sminshall 		    if (c == DISP_QUESTION) {
665*30015Sminshall 			AddHost(i, DISP_GREATER_THAN);
666*30015Sminshall 			TurnOnMdt(i);
667*30015Sminshall 		    } else if (c == DISP_GREATER_THAN) {
668*30015Sminshall 			AddHost(i, DISP_QUESTION);
669*30015Sminshall 			TurnOffMdt(i);
670*30015Sminshall 		    } else if (c == DISP_BLANK || c == DISP_NULL
671*30015Sminshall 						|| c == DISP_AMPERSAND) {
672*30015Sminshall 			UnLocked = 0;
673*30015Sminshall 			InsertMode = 0;
674*30015Sminshall 			if (c == DISP_AMPERSAND) {
675*30015Sminshall 			    TurnOnMdt(i);	/* Only for & type */
676*30015Sminshall 			    AidByte = AID_ENTER;
677*30015Sminshall 			} else {
678*30015Sminshall 			    AidByte = AID_SELPEN;
679*30015Sminshall 			}
680*30015Sminshall 			HadAid = 1;
681*30015Sminshall 			SendToIBM();
682*30015Sminshall 		    } else {
683*30015Sminshall 			RingBell(
684*30015Sminshall 			    "Cursor not in a selectable field (designator)");
685*30015Sminshall 		    }
686*30015Sminshall 		}
687*30015Sminshall 		break;
688*30015Sminshall 
689*30015Sminshall 	    case FCN_ERASE:
690*30015Sminshall 		if (IsProtected(ScreenDec(CursorAddress))) {
691*30015Sminshall 		    RingBell("Protected Field");
692*30015Sminshall 		} else {
693*30015Sminshall 		    CursorAddress = ScreenDec(CursorAddress);
694*30015Sminshall 		    Delete(CursorAddress, ScreenInc(CursorAddress));
695*30015Sminshall 		}
696*30015Sminshall 		break;
697*30015Sminshall 
698*30015Sminshall 	    case FCN_WERASE:
699*30015Sminshall 		j = CursorAddress;
700*30015Sminshall 		i = ScreenDec(j);
701*30015Sminshall 		if (IsProtected(i)) {
702*30015Sminshall 		    RingBell("Protected Field");
703*30015Sminshall 		} else {
704*30015Sminshall 		    SetXIsProtected();
705*30015Sminshall 		    while ((!XIsProtected(i) && Disspace(GetHost(i)))
706*30015Sminshall 							&& (i != j)) {
707*30015Sminshall 			i = ScreenDec(i);
708*30015Sminshall 		    }
709*30015Sminshall 		    /* we are pointing at a character in a word, or
710*30015Sminshall 		     * at a protected position
711*30015Sminshall 		     */
712*30015Sminshall 		    while ((!XIsProtected(i) && !Disspace(GetHost(i)))
713*30015Sminshall 							&& (i != j)) {
714*30015Sminshall 			i = ScreenDec(i);
715*30015Sminshall 		    }
716*30015Sminshall 		    /* we are pointing at a space, or at a protected
717*30015Sminshall 		     * position
718*30015Sminshall 		     */
719*30015Sminshall 		    CursorAddress = ScreenInc(i);
720*30015Sminshall 		    Delete(CursorAddress, j);
721*30015Sminshall 		}
722*30015Sminshall 		break;
723*30015Sminshall 
724*30015Sminshall 	    case FCN_FERASE:
725*30015Sminshall 		if (IsProtected(CursorAddress)) {
726*30015Sminshall 		    RingBell("Protected Field");
727*30015Sminshall 		} else {
728*30015Sminshall 		    CursorAddress = ScreenInc(CursorAddress);	/* for btab */
729*30015Sminshall 		    BackTab();
730*30015Sminshall 		    EraseEndOfField();
731*30015Sminshall 		}
732*30015Sminshall 		break;
733*30015Sminshall 
734*30015Sminshall 	    case FCN_RESET:
735*30015Sminshall 		InsertMode = 0;
736*30015Sminshall 		break;
737*30015Sminshall 
738*30015Sminshall 	    case FCN_MASTER_RESET:
739*30015Sminshall 		InsertMode = 0;
740*30015Sminshall 		RefreshScreen();
741*30015Sminshall 		break;
742*30015Sminshall 
743*30015Sminshall 	    case FCN_UP:
744*30015Sminshall 		CursorAddress = ScreenUp(CursorAddress);
745*30015Sminshall 		break;
746*30015Sminshall 
747*30015Sminshall 	    case FCN_LEFT:
748*30015Sminshall 		CursorAddress = ScreenDec(CursorAddress);
749*30015Sminshall 		break;
750*30015Sminshall 
751*30015Sminshall 	    case FCN_RIGHT:
752*30015Sminshall 		CursorAddress = ScreenInc(CursorAddress);
753*30015Sminshall 		break;
754*30015Sminshall 
755*30015Sminshall 	    case FCN_DOWN:
756*30015Sminshall 		CursorAddress = ScreenDown(CursorAddress);
757*30015Sminshall 		break;
758*30015Sminshall 
759*30015Sminshall 	    case FCN_DELETE:
760*30015Sminshall 		if (IsProtected(CursorAddress)) {
761*30015Sminshall 		    RingBell("Protected Field");
762*30015Sminshall 		} else {
763*30015Sminshall 		    Delete(CursorAddress, ScreenInc(CursorAddress));
764*30015Sminshall 		}
765*30015Sminshall 		break;
766*30015Sminshall 
767*30015Sminshall 	    case FCN_INSRT:
768*30015Sminshall 		InsertMode = !InsertMode;
769*30015Sminshall 		break;
770*30015Sminshall 
771*30015Sminshall 	    case FCN_HOME:
772*30015Sminshall 		Home();
773*30015Sminshall 		break;
774*30015Sminshall 
775*30015Sminshall 	    case FCN_NL:
776*30015Sminshall 		/* The algorithm is to look for the first unprotected
777*30015Sminshall 		 * column after column 0 of the following line.  Having
778*30015Sminshall 		 * found that unprotected column, we check whether the
779*30015Sminshall 		 * cursor-address-at-entry is at or to the right of the
780*30015Sminshall 		 * LeftMargin AND the LeftMargin column of the found line
781*30015Sminshall 		 * is unprotected.  If this conjunction is true, then
782*30015Sminshall 		 * we set the found pointer to the address of the LeftMargin
783*30015Sminshall 		 * column in the found line.
784*30015Sminshall 		 * Then, we set the cursor address to the found address.
785*30015Sminshall 		 */
786*30015Sminshall 		i = SetBufferAddress(ScreenLine(ScreenDown(CursorAddress)), 0);
787*30015Sminshall 		j = ScreenInc(WhereAttrByte(CursorAddress));
788*30015Sminshall 		do {
789*30015Sminshall 		    if (IsUnProtected(i)) {
790*30015Sminshall 			break;
791*30015Sminshall 		    }
792*30015Sminshall 		    /* Again (see comment in Home()), this COULD be a problem
793*30015Sminshall 		     * with an unformatted screen.
794*30015Sminshall 		     */
795*30015Sminshall 		    /* If there was a field with only an attribute byte,
796*30015Sminshall 		     * we may be pointing to the attribute byte of the NEXT
797*30015Sminshall 		     * field, so just look at the next byte.
798*30015Sminshall 		     */
799*30015Sminshall 		    if (IsStartField(i)) {
800*30015Sminshall 			i = ScreenInc(i);
801*30015Sminshall 		    } else {
802*30015Sminshall 			i = ScreenInc(FieldInc(i));
803*30015Sminshall 		    }
804*30015Sminshall 		} while (i != j);
805*30015Sminshall 		if (!IsUnProtected(i)) {	/* couldn't find unprotected */
806*30015Sminshall 		    i = SetBufferAddress(0,0);
807*30015Sminshall 		}
808*30015Sminshall 		if (OptLeftMargin <= ScreenLineOffset(CursorAddress)) {
809*30015Sminshall 		    if (IsUnProtected(SetBufferAddress(ScreenLine(i),
810*30015Sminshall 							    OptLeftMargin))) {
811*30015Sminshall 			i = SetBufferAddress(ScreenLine(i), OptLeftMargin);
812*30015Sminshall 		    }
813*30015Sminshall 		}
814*30015Sminshall 		CursorAddress = i;
815*30015Sminshall 		break;
816*30015Sminshall 
817*30015Sminshall 	    case FCN_EINP:
818*30015Sminshall 		if (!FormattedScreen()) {
819*30015Sminshall 		    i = CursorAddress;
820*30015Sminshall 		    TurnOnMdt(i);
821*30015Sminshall 		    do {
822*30015Sminshall 			AddHost(i, 0);
823*30015Sminshall 			i = ScreenInc(i);
824*30015Sminshall 		    } while (i != CursorAddress);
825*30015Sminshall 		} else {
826*30015Sminshall 			/*
827*30015Sminshall 			 * The algorithm is:  go through each unprotected
828*30015Sminshall 			 * field on the screen, clearing it out.  When
829*30015Sminshall 			 * we are at the start of a field, skip that field
830*30015Sminshall 			 * if its contents are protected.
831*30015Sminshall 			 */
832*30015Sminshall 		    i = j = FieldInc(CursorAddress);
833*30015Sminshall 		    do {
834*30015Sminshall 			if (IsUnProtected(ScreenInc(i))) {
835*30015Sminshall 			    i = ScreenInc(i);
836*30015Sminshall 			    TurnOnMdt(i);
837*30015Sminshall 			    do {
838*30015Sminshall 			       AddHost(i, 0);
839*30015Sminshall 			       i = ScreenInc(i);
840*30015Sminshall 			    } while (!IsStartField(i));
841*30015Sminshall 			} else {
842*30015Sminshall 			    i = FieldInc(i);
843*30015Sminshall 			}
844*30015Sminshall 		    } while (i != j);
845*30015Sminshall 		}
846*30015Sminshall 		Home();
847*30015Sminshall 		break;
848*30015Sminshall 
849*30015Sminshall 	    case FCN_EEOF:
850*30015Sminshall 		EraseEndOfField();
851*30015Sminshall 		break;
852*30015Sminshall 
853*30015Sminshall 	    case FCN_SPACE:
854*30015Sminshall 		OneCharacter(DISP_BLANK, InsertMode);  /* Add cent */
855*30015Sminshall 		break;
856*30015Sminshall 
857*30015Sminshall 	    case FCN_CENTSIGN:
858*30015Sminshall 		OneCharacter(DISP_CENTSIGN, InsertMode);  /* Add cent */
859*30015Sminshall 		break;
860*30015Sminshall 
861*30015Sminshall 	    case FCN_FM:
862*30015Sminshall 		OneCharacter(DISP_FM, InsertMode);  /* Add field mark */
863*30015Sminshall 		break;
864*30015Sminshall 
865*30015Sminshall 	    case FCN_DP:
866*30015Sminshall 		if (IsProtected(CursorAddress)) {
867*30015Sminshall 		    RingBell("Protected Field");
868*30015Sminshall 		} else {
869*30015Sminshall 		    OneCharacter(DISP_DUP, InsertMode);/* Add dup character */
870*30015Sminshall 		    Tab();
871*30015Sminshall 		}
872*30015Sminshall 		break;
873*30015Sminshall 
874*30015Sminshall 	    case FCN_TAB:
875*30015Sminshall 		Tab();
876*30015Sminshall 		break;
877*30015Sminshall 
878*30015Sminshall 	    case FCN_BTAB:
879*30015Sminshall 		BackTab();
880*30015Sminshall 		break;
881*30015Sminshall 
882*30015Sminshall #ifdef	NOTUSED			/* Actually, this is superseded by unix flow
883*30015Sminshall 				 * control.
884*30015Sminshall 				 */
885*30015Sminshall 	    case FCN_XOFF:
886*30015Sminshall 		Flow = 0;			/* stop output */
887*30015Sminshall 		break;
888*30015Sminshall 
889*30015Sminshall 	    case FCN_XON:
890*30015Sminshall 		if (!Flow) {
891*30015Sminshall 		    Flow = 1;			/* turn it back on */
892*30015Sminshall 		    DoTerminalOutput();
893*30015Sminshall 		}
894*30015Sminshall 		break;
895*30015Sminshall #endif	/* NOTUSED */
896*30015Sminshall 
897*30015Sminshall 	    case FCN_ESCAPE:
898*30015Sminshall 		/* FlushChar(); do we want to flush characters from before? */
899*30015Sminshall 		StopScreen(1);
900*30015Sminshall 		command(0);
901*30015Sminshall 		ConnectScreen();
902*30015Sminshall 		break;
903*30015Sminshall 
904*30015Sminshall 	    case FCN_DISC:
905*30015Sminshall 		StopScreen(1);
906*30015Sminshall 		suspend();
907*30015Sminshall 		ConnectScreen();
908*30015Sminshall 		break;
909*30015Sminshall 
910*30015Sminshall 	    case FCN_RESHOW:
911*30015Sminshall 		RefreshScreen();
912*30015Sminshall 		break;
913*30015Sminshall 
914*30015Sminshall 	    case FCN_SETTAB:
915*30015Sminshall 		OptColTabs[ScreenLineOffset(CursorAddress)] = 1;
916*30015Sminshall 		break;
917*30015Sminshall 
918*30015Sminshall 	    case FCN_DELTAB:
919*30015Sminshall 		OptColTabs[ScreenLineOffset(CursorAddress)] = 0;
920*30015Sminshall 		break;
921*30015Sminshall 
922*30015Sminshall 		/*
923*30015Sminshall 		 * Clear all tabs, home line, and left margin.
924*30015Sminshall 		 */
925*30015Sminshall 	    case FCN_CLRTAB:
926*30015Sminshall 		for (i = 0; i < sizeof OptColTabs; i++) {
927*30015Sminshall 		    OptColTabs[i] = 0;
928*30015Sminshall 		}
929*30015Sminshall 		OptHome = 0;
930*30015Sminshall 		OptLeftMargin = 0;
931*30015Sminshall 		break;
932*30015Sminshall 
933*30015Sminshall 	    case FCN_COLTAB:
934*30015Sminshall 		ColTab();
935*30015Sminshall 		break;
936*30015Sminshall 
937*30015Sminshall 	    case FCN_COLBAK:
938*30015Sminshall 		ColBak();
939*30015Sminshall 		break;
940*30015Sminshall 
941*30015Sminshall 	    case FCN_INDENT:
942*30015Sminshall 		ColTab();
943*30015Sminshall 		OptLeftMargin = ScreenLineOffset(CursorAddress);
944*30015Sminshall 		break;
945*30015Sminshall 
946*30015Sminshall 	    case FCN_UNDENT:
947*30015Sminshall 		ColBak();
948*30015Sminshall 		OptLeftMargin = ScreenLineOffset(CursorAddress);
949*30015Sminshall 		break;
950*30015Sminshall 
951*30015Sminshall 	    case FCN_SETMRG:
952*30015Sminshall 		OptLeftMargin = ScreenLineOffset(CursorAddress);
953*30015Sminshall 		break;
954*30015Sminshall 
955*30015Sminshall 	    case FCN_SETHOM:
956*30015Sminshall 		OptHome = ScreenLine(CursorAddress);
957*30015Sminshall 		break;
958*30015Sminshall 
959*30015Sminshall 		/*
960*30015Sminshall 		 * Point to first character of next unprotected word on
961*30015Sminshall 		 * screen.
962*30015Sminshall 		 */
963*30015Sminshall 	    case FCN_WORDTAB:
964*30015Sminshall 		i = CursorAddress;
965*30015Sminshall 		SetXIsProtected();
966*30015Sminshall 		while (!XIsProtected(i) && !Disspace(GetHost(i))) {
967*30015Sminshall 		    i = ScreenInc(i);
968*30015Sminshall 		    if (i == CursorAddress) {
969*30015Sminshall 			break;
970*30015Sminshall 		    }
971*30015Sminshall 		}
972*30015Sminshall 		/* i is either protected, a space (blank or null),
973*30015Sminshall 		 * or wrapped
974*30015Sminshall 		 */
975*30015Sminshall 		while (XIsProtected(i) || Disspace(GetHost(i))) {
976*30015Sminshall 		    i =  ScreenInc(i);
977*30015Sminshall 		    if (i == CursorAddress) {
978*30015Sminshall 			break;
979*30015Sminshall 		    }
980*30015Sminshall 		}
981*30015Sminshall 		CursorAddress = i;
982*30015Sminshall 		break;
983*30015Sminshall 
984*30015Sminshall 	    case FCN_WORDBACKTAB:
985*30015Sminshall 		i = ScreenDec(CursorAddress);
986*30015Sminshall 		SetXIsProtected();
987*30015Sminshall 		while (XIsProtected(i) || Disspace(GetHost(i))) {
988*30015Sminshall 		    i = ScreenDec(i);
989*30015Sminshall 		    if (i == CursorAddress) {
990*30015Sminshall 			break;
991*30015Sminshall 		    }
992*30015Sminshall 		}
993*30015Sminshall 		    /* i is pointing to a character IN an unprotected word
994*30015Sminshall 		     * (or i wrapped)
995*30015Sminshall 		     */
996*30015Sminshall 		while (!Disspace(GetHost(i))) {
997*30015Sminshall 		    i = ScreenDec(i);
998*30015Sminshall 		    if (i == CursorAddress) {
999*30015Sminshall 			break;
1000*30015Sminshall 		    }
1001*30015Sminshall 		}
1002*30015Sminshall 		CursorAddress = ScreenInc(i);
1003*30015Sminshall 		break;
1004*30015Sminshall 
1005*30015Sminshall 			/* Point to last non-blank character of this/next
1006*30015Sminshall 			 * unprotected word.
1007*30015Sminshall 			 */
1008*30015Sminshall 	    case FCN_WORDEND:
1009*30015Sminshall 		i = ScreenInc(CursorAddress);
1010*30015Sminshall 		SetXIsProtected();
1011*30015Sminshall 		while (XIsProtected(i) || Disspace(GetHost(i))) {
1012*30015Sminshall 		    i = ScreenInc(i);
1013*30015Sminshall 		    if (i == CursorAddress) {
1014*30015Sminshall 			break;
1015*30015Sminshall 		    }
1016*30015Sminshall 		}
1017*30015Sminshall 			/* we are pointing at a character IN an
1018*30015Sminshall 			 * unprotected word (or we wrapped)
1019*30015Sminshall 			 */
1020*30015Sminshall 		while (!Disspace(GetHost(i))) {
1021*30015Sminshall 		    i = ScreenInc(i);
1022*30015Sminshall 		    if (i == CursorAddress) {
1023*30015Sminshall 			break;
1024*30015Sminshall 		    }
1025*30015Sminshall 		}
1026*30015Sminshall 		CursorAddress = ScreenDec(i);
1027*30015Sminshall 		break;
1028*30015Sminshall 
1029*30015Sminshall 			/* Get to last non-blank of this/next unprotected
1030*30015Sminshall 			 * field.
1031*30015Sminshall 			 */
1032*30015Sminshall 	    case FCN_FIELDEND:
1033*30015Sminshall 		i = LastOfField(CursorAddress);
1034*30015Sminshall 		if (i != CursorAddress) {
1035*30015Sminshall 		    CursorAddress = i;		/* We moved; take this */
1036*30015Sminshall 		} else {
1037*30015Sminshall 		    j = FieldInc(CursorAddress);	/* Move to next field */
1038*30015Sminshall 		    i = LastOfField(j);
1039*30015Sminshall 		    if (i != j) {
1040*30015Sminshall 			CursorAddress = i;	/* We moved; take this */
1041*30015Sminshall 		    }
1042*30015Sminshall 			/* else - nowhere else on screen to be; stay here */
1043*30015Sminshall 		}
1044*30015Sminshall 		break;
1045*30015Sminshall 
1046*30015Sminshall 	    default:
1047*30015Sminshall 				    /* We don't handle this yet */
1048*30015Sminshall 		RingBell("Function not implemented");
1049*30015Sminshall 	    }
1050*30015Sminshall 	}
1051*30015Sminshall     }
1052*30015Sminshall     return(origCount-count);
1053*30015Sminshall }
1054