Sync usage with man page.
[netbsd-mini2440.git] / usr.bin / tn3270 / ctlr / inbound.c
bloba689f9837c7a5b87db511eb0876222f41cfb569e
1 /* $NetBSD: inbound.c,v 1.6 2002/06/13 23:41:19 wiz Exp $ */
3 /*-
4 * Copyright (c) 1988 The Regents of the University of California.
5 * All rights reserved.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the University nor the names of its contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
32 #include <sys/cdefs.h>
33 #ifndef lint
34 #if 0
35 static char sccsid[] = "@(#)inbound.c 4.3 (Berkeley) 4/26/91";
36 #else
37 __RCSID("$NetBSD: inbound.c,v 1.6 2002/06/13 23:41:19 wiz Exp $");
38 #endif
39 #endif /* not lint */
41 #include <stdio.h>
43 #include "../general/general.h"
44 #include "function.h"
45 #include "hostctlr.h"
46 #include "oia.h"
47 #include "scrnctlr.h"
48 #include "screen.h"
49 #include "options.h"
50 #include "../api/dctype.h"
51 #include "../api/ebc_disp.h"
53 #include "../general/globals.h"
54 #include "../sys_curses/telextrn.h"
55 #include "externs.h"
56 #include "declare.h"
58 #define EmptyChar() (ourPTail == ourPHead)
59 #define FullChar() (ourPHead == ourBuffer+sizeof ourBuffer)
63 * We define something to allow us to to IsProtected() quickly
64 * on unformatted screens (with the current algorithm for fields,
65 * unprotected takes exponential time...).
67 * The idea is to call SetXIsProtected() BEFORE the
68 * loop, then use XIsProtected().
71 #define SetXIsProtected() (XWasSF = 1)
72 #define XIsProtected(p) (IsStartField(p) ? \
73 (XWasSF = 1) : \
74 (XWasSF ? \
75 (XWasSF = 0, XProtected = IsProtected(p)) : \
76 XProtected))
78 static char ourBuffer[400];
80 static char *ourPHead = ourBuffer,
81 *ourPTail = ourBuffer;
83 static int HadAid; /* Had an AID haven't sent */
85 static int InsertMode; /* is the terminal in insert mode? */
87 static unsigned int
88 rememberedshiftstate; /* Shift (alt) state of terminal */
90 # define HITNUM(s) ((((s)&(SHIFT_CAPS|SHIFT_UPSHIFT))? 1:0) \
91 + ((((s)&SHIFT_ALT)? 1:0)<<1))
93 static int XWasSF, XProtected; /* For optimizations */
94 #if !defined(PURE3274)
95 extern int TransparentClock, OutputClock;
96 #endif /* !defined(PURE3274) */
98 #include "kbd.out" /* Get keyboard mapping function */
100 /* the following are global variables */
102 extern int UnLocked; /* keyboard is UnLocked? */
105 static void Tab(void);
106 static void BackTab(void);
107 static void EraseEndOfField(void);
108 static void Delete(int, int );
109 static void ColBak(void);
110 static void ColTab(void);
111 static void Home(void);
112 static int LastOfField(int);
113 static void FlushChar(void);
114 static void AddChar(int);
115 static void SendUnformatted(void);
116 static int SendField(int, int);
117 static void OneCharacter(int, int);
120 * init_inbound :
122 * Reset variables to initial state.
125 void
126 init_inbound()
128 ourPHead = ourPTail = ourBuffer;
129 HadAid = 0;
130 rememberedshiftstate = 0;
131 InsertMode = 0;
135 /* Tab() - sets cursor to the start of the next unprotected field */
136 static void
137 Tab()
139 int i, j;
141 i = CursorAddress;
142 j = WhereAttrByte(CursorAddress);
143 do {
144 if (IsStartField(i) && IsUnProtected(ScreenInc(i))) {
145 break;
147 i = FieldInc(i);
148 } while (i != j);
149 if (IsStartField(i) && IsUnProtected(ScreenInc(i))) {
150 CursorAddress = ScreenInc(i);
151 } else {
152 CursorAddress = SetBufferAddress(0,0);
157 /* BackTab() - sets cursor to the start of the most recent field */
159 static void
160 BackTab()
162 int i;
164 i = ScreenDec(CursorAddress);
165 for (;;) {
166 if (IsStartField(ScreenDec(i)) && IsUnProtected(i)) {
167 CursorAddress = i;
168 break;
170 if (i == CursorAddress) {
171 CursorAddress = SetBufferAddress(0,0);
172 break;
174 i = ScreenDec(i);
179 * ModifyMdt() - Turn a modified data tag bit on or off (watch
180 * out for unformatted screens).
183 void
184 ModifyMdt(x,on)
185 int x;
186 int on;
188 int i = x;
190 if (IsStartField(i)) { /* If we are at a start field position... */
191 if (on) {
192 ModifyHost(i, |= ATTR_MDT); /* Turn it on */
193 } else {
194 ModifyHost(i, &= ~ATTR_MDT); /* Turn it off */
196 } else {
197 i = WhereAttrByte(i); /* Find beginning of field */
198 if (IsStartField(i)) { /* Is there one? */
199 if (on) {
200 ModifyHost(i, |= ATTR_MDT); /* Turn it on */
201 } else {
202 ModifyHost(i, &= ~ATTR_MDT); /* Turn it off */
204 } /* else, don't modify - this is an unformatted screen */
209 /* EraseEndOfField - erase all characters to the end of a field */
211 static void
212 EraseEndOfField()
214 int i;
216 if (IsProtected(CursorAddress)) {
217 RingBell("Protected Field");
218 } else {
219 TurnOnMdt(CursorAddress);
220 if (FormattedScreen()) {
221 i = CursorAddress;
222 do {
223 AddHost(i, 0);
224 i = ScreenInc(i);
225 } while ((i != CursorAddress) && !IsStartField(i));
226 } else { /* Screen is Unformatted */
227 i = CursorAddress;
228 do {
229 AddHost(i, 0);
230 i = ScreenInc(i);
231 } while (i != HighestScreen());
236 /* Delete() - deletes a character from the screen
238 * What we want to do is delete the section
239 * [where, from-1] from the screen,
240 * filling in with what comes at from.
242 * The deleting continues to the end of the field (or
243 * until the cursor wraps).
245 * From can be a start of a field. We
246 * check for that. However, there can't be any
247 * fields that start between where and from.
248 * We don't check for that.
250 * Also, we assume that the protection status of
251 * everything has been checked by the caller.
255 static void
256 Delete(where, from)
257 int where, /* Where to start deleting from */
258 from; /* Where to pull back from */
260 int i;
262 TurnOnMdt(where); /* Only do this once in this field */
263 i = where;
264 do {
265 if (IsStartField(from)) {
266 AddHost(i, 0); /* Stick the edge at the start field */
267 } else {
268 AddHost(i, (char)GetHost(from));
269 from = ScreenInc(from); /* Move the edge */
271 i = ScreenInc(i);
272 } while ((!IsStartField(i)) && (i != where));
275 static void
276 ColBak()
278 int i;
280 i = ScreenLineOffset(CursorAddress);
281 for (i = i-1; i >= 0; i--) {
282 if (OptColTabs[i]) {
283 break;
286 if (i < 0) {
287 i = 0;
289 CursorAddress = SetBufferAddress(ScreenLine(CursorAddress), i);
292 static void
293 ColTab()
295 int i;
297 i = ScreenLineOffset(CursorAddress);
298 for (i = i+1; i < NumberColumns; i++) {
299 if (OptColTabs[i]) {
300 break;
303 if (i >= NumberColumns) {
304 i = NumberColumns-1;
306 CursorAddress = SetBufferAddress(ScreenLine(CursorAddress), i);
309 static void
310 Home()
312 int i;
313 int j;
315 i = SetBufferAddress(OptHome, 0);
316 j = WhereLowByte(i);
318 * If the initial value of i points to the field attribute of
319 * an unprotected field, we need to return the address of the
320 * first data byte in the field (assuming there are any!).
322 if (IsStartField(i) && IsUnProtected(j)) {
323 CursorAddress = j;
324 return;
326 do {
327 if (IsUnProtected(i)) {
328 CursorAddress = i;
329 return;
331 /* the following could be a problem if we got here with an
332 * unformatted screen. However, this is "impossible", since
333 * with an unformatted screen, the IsUnProtected(i) above
334 * should be true.
336 i = ScreenInc(FieldInc(i));
337 } while (i != j);
338 CursorAddress = LowestScreen();
341 static int
342 LastOfField(i)
343 int i; /* position to start from */
345 int j;
346 int k;
348 k = j = i;
349 SetXIsProtected();
350 while (XIsProtected(i) || Disspace(GetHost(i))) {
351 i = ScreenInc(i);
352 if (i == j) {
353 break;
356 /* We are now IN a word IN an unprotected field (or wrapped) */
357 while (!XIsProtected(i)) {
358 if (!Disspace(GetHost(i))) {
359 k = i;
361 i = ScreenInc(i);
362 if (i == j) {
363 break;
366 return(k);
370 static void
371 FlushChar()
373 ourPTail = ourPHead = ourBuffer;
378 * Add one EBCDIC (NOT display code) character to the buffer.
381 static void
382 AddChar(character)
383 char character;
385 if (FullChar()) {
386 ourPTail += DataToNetwork(ourPTail, ourPHead-ourPTail, 0);
387 if (EmptyChar()) {
388 FlushChar();
389 } else {
390 char buffer[100];
392 sprintf(buffer, "File %s, line %d: No room in network buffer!\n",
393 __FILE__, __LINE__);
394 ExitString(buffer, 1);
395 /*NOTREACHED*/
398 *ourPHead++ = character;
402 static void
403 SendUnformatted()
405 int i, j;
406 int Nulls;
407 int c;
409 /* look for start of field */
410 Nulls = 0;
411 i = j = LowestScreen();
412 do {
413 c = GetHost(i);
414 if (c == 0) {
415 Nulls++;
416 } else {
417 while (Nulls) {
418 Nulls--;
419 AddChar(EBCDIC_BLANK); /* put in blanks */
421 AddChar((char)disp_ebc[c]);
423 i = ScreenInc(i);
424 } while (i != j);
427 static int
428 SendField(i, cmd)
429 int i; /* where we saw MDT bit */
430 int cmd; /* The command code (type of read) */
432 int j;
433 int k;
434 int Nulls;
435 int c;
437 /* look for start of field */
438 i = j = WhereLowByte(i);
440 /* On a test_request_read, don't send sba and address */
441 if ((AidByte != AID_TREQ)
442 || (cmd == CMD_SNA_READ_MODIFIED_ALL)) {
443 AddChar(ORDER_SBA); /* set start field */
444 AddChar(BufferTo3270_0(j)); /* set address of this field */
445 AddChar(BufferTo3270_1(j));
448 * Only on read_modified_all do we return the contents
449 * of the field when the attention was caused by a
450 * selector pen.
452 if ((AidByte != AID_SELPEN)
453 || (cmd == CMD_SNA_READ_MODIFIED_ALL)) {
454 if (!IsStartField(j)) {
455 Nulls = 0;
456 k = ScreenInc(WhereHighByte(j));
457 do {
458 c = GetHost(j);
459 if (c == 0) {
460 Nulls++;
461 } else {
462 while (Nulls) {
463 Nulls--;
464 AddChar(EBCDIC_BLANK); /* put in blanks */
466 AddChar((char)disp_ebc[c]);
468 j = ScreenInc(j);
469 } while ((j != k) && (j != i));
471 } else {
472 j = FieldInc(j);
474 return(j);
477 /* Various types of reads... */
478 void
479 DoReadModified(cmd)
480 int cmd; /* The command sent */
482 int i, j;
484 if (AidByte) {
485 if (AidByte != AID_TREQ) {
486 AddChar(AidByte);
487 } else {
488 /* Test Request Read header */
489 AddChar(EBCDIC_SOH);
490 AddChar(EBCDIC_PERCENT);
491 AddChar(EBCDIC_SLASH);
492 AddChar(EBCDIC_STX);
494 } else {
495 AddChar(AID_NONE);
497 if (((AidByte != AID_PA1) && (AidByte != AID_PA2)
498 && (AidByte != AID_PA3) && (AidByte != AID_CLEAR))
499 || (cmd == CMD_SNA_READ_MODIFIED_ALL)) {
500 if ((AidByte != AID_TREQ)
501 || (cmd == CMD_SNA_READ_MODIFIED_ALL)) {
502 /* Test request read_modified doesn't give cursor address */
503 AddChar(BufferTo3270_0(CursorAddress));
504 AddChar(BufferTo3270_1(CursorAddress));
506 i = j = WhereAttrByte(LowestScreen());
507 /* Is this an unformatted screen? */
508 if (!IsStartField(i)) { /* yes, handle separate */
509 SendUnformatted();
510 } else {
511 do {
512 if (HasMdt(i)) {
513 i = SendField(i, cmd);
514 } else {
515 i = FieldInc(i);
517 } while (i != j);
520 ourPTail += DataToNetwork(ourPTail, ourPHead-ourPTail, 1);
521 if (EmptyChar()) {
522 FlushChar();
523 HadAid = 0; /* killed that buffer */
527 /* A read buffer operation... */
529 void
530 DoReadBuffer()
532 int i, j;
534 if (AidByte) {
535 AddChar(AidByte);
536 } else {
537 AddChar(AID_NONE);
539 AddChar(BufferTo3270_0(CursorAddress));
540 AddChar(BufferTo3270_1(CursorAddress));
541 i = j = LowestScreen();
542 do {
543 if (IsStartField(i)) {
544 AddChar(ORDER_SF);
545 AddChar(BufferTo3270_1(FieldAttributes(i)));
546 } else {
547 AddChar((char)disp_ebc[GetHost(i)]);
549 i = ScreenInc(i);
550 } while (i != j);
551 ourPTail += DataToNetwork(ourPTail, ourPHead-ourPTail, 1);
552 if (EmptyChar()) {
553 FlushChar();
554 HadAid = 0; /* killed that buffer */
558 /* Send some transparent data to the host */
560 void
561 SendTransparent(buffer, count)
562 char *buffer;
563 int count;
565 char stuff[3];
567 stuff[0] = AID_NONE_PRINTER;
568 stuff[1] = BufferTo3270_0(count);
569 stuff[2] = BufferTo3270_1(count);
570 DataToNetwork(stuff, sizeof stuff, 0);
571 DataToNetwork(buffer, count, 1);
575 /* Try to send some data to host */
577 void
578 SendToIBM()
580 #if !defined(PURE3274)
581 if (TransparentClock >= OutputClock) {
582 if (HadAid) {
583 AddChar(AidByte);
584 HadAid = 0;
585 } else {
586 AddChar(AID_NONE_PRINTER);
588 do {
589 ourPTail += DataToNetwork(ourPTail, ourPHead-ourPTail, 1);
590 } while (!EmptyChar());
591 FlushChar();
592 } else if (HadAid) {
593 DoReadModified(CMD_READ_MODIFIED);
595 #else /* !defined(PURE3274) */
596 if (HadAid) {
597 DoReadModified(CMD_READ_MODIFIED);
599 #endif /* !defined(PURE3274) */
602 /* This takes in one character from the keyboard and places it on the
603 * screen.
606 static void
607 OneCharacter(c, insert)
608 int c; /* character (Ebcdic) to be shoved in */
609 int insert; /* are we in insert mode? */
611 int i, j;
613 if (IsProtected(CursorAddress)) {
614 RingBell("Protected Field");
615 return;
617 if (insert) {
618 /* is the last character in the field a blank or null? */
619 i = ScreenDec(FieldInc(CursorAddress));
620 j = GetHost(i);
621 if (!Disspace(j)) {
622 RingBell("No more room for insert");
623 return;
624 } else {
625 for (j = ScreenDec(i); i != CursorAddress;
626 j = ScreenDec(j), i = ScreenDec(i)) {
627 AddHost(i, (char)GetHost(j));
631 AddHost(CursorAddress, c);
632 TurnOnMdt(CursorAddress);
633 CursorAddress = ScreenInc(CursorAddress);
634 if (IsStartField(CursorAddress) &&
635 ((FieldAttributes(CursorAddress)&ATTR_AUTO_SKIP_MASK) ==
636 ATTR_AUTO_SKIP_VALUE)) {
637 Tab();
642 * AcceptKeystroke()
644 * Processes one keystroke.
646 * Returns:
648 * 0 if this keystroke was NOT processed.
649 * 1 if everything went OK.
653 AcceptKeystroke(scancode, shiftstate)
654 unsigned int
655 scancode, /* 3270 scancode */
656 shiftstate; /* The shift state */
658 int c;
659 int i;
660 int j;
661 enum ctlrfcn ctlrfcn;
663 if (scancode >= numberof(hits)) {
664 ExitString(
665 "Unknown scancode encountered in AcceptKeystroke.\n", 1);
666 /*NOTREACHED*/
668 ctlrfcn = hits[scancode].hit[HITNUM(shiftstate)].ctlrfcn;
669 c = hits[scancode].hit[HITNUM(shiftstate)].code;
671 if (!UnLocked || HadAid) {
672 if (HadAid) {
673 SendToIBM();
674 if (!EmptyChar()) {
675 return 0; /* nothing to do */
678 #if !defined(PURE3274)
679 if (!HadAid && EmptyChar()) {
680 if ((ctlrfcn == FCN_RESET) || (ctlrfcn == FCN_MASTER_RESET)) {
681 UnLocked = 1;
684 #endif /* !defined(PURE3274) */
685 if (!UnLocked) {
686 return 0;
690 /* now, either empty, or haven't seen aid yet */
692 #if !defined(PURE3274)
694 * If we are in transparent (output) mode, do something special
695 * with keystrokes.
697 if (TransparentClock == OutputClock) {
698 if (ctlrfcn == FCN_AID) {
699 UnLocked = 0;
700 InsertMode = 0;
701 AidByte = (c);
702 HadAid = 1;
703 } else {
704 switch (ctlrfcn) {
705 case FCN_ESCAPE:
706 StopScreen(1);
707 command(0, NULL, 0);
708 if (shell_active == 0) {
709 ConnectScreen();
711 break;
713 case FCN_RESET:
714 case FCN_MASTER_RESET:
715 UnLocked = 1;
716 break;
718 default:
719 return 0;
723 #endif /* !defined(PURE3274) */
725 if (ctlrfcn == FCN_CHARACTER) {
726 /* Add the character to the buffer */
727 OneCharacter(c, InsertMode);
728 } else if (ctlrfcn == FCN_AID) { /* got Aid */
729 if (c == AID_CLEAR) {
730 LocalClearScreen(); /* Side effect is to clear 3270 */
732 ResetOiaOnlineA(&OperatorInformationArea);
733 SetOiaTWait(&OperatorInformationArea);
734 ResetOiaInsert(&OperatorInformationArea);
735 InsertMode = 0; /* just like a 3278 */
736 SetOiaSystemLocked(&OperatorInformationArea);
737 SetOiaModified();
738 UnLocked = 0;
739 AidByte = c;
740 HadAid = 1;
741 SendToIBM();
742 } else {
743 switch (ctlrfcn) {
745 case FCN_CURSEL:
746 c = FieldAttributes(CursorAddress)&ATTR_DSPD_MASK;
747 if (!FormattedScreen()
748 || ((c != ATTR_DSPD_DSPD) && (c != ATTR_DSPD_HIGH))) {
749 RingBell("Cursor not in selectable field");
750 } else {
751 i = ScreenInc(WhereAttrByte(CursorAddress));
752 c = GetHost(i);
753 if (c == DISP_QUESTION) {
754 AddHost(i, DISP_GREATER_THAN);
755 TurnOnMdt(i);
756 } else if (c == DISP_GREATER_THAN) {
757 AddHost(i, DISP_QUESTION);
758 TurnOffMdt(i);
759 } else if (c == DISP_BLANK || c == DISP_NULL
760 || c == DISP_AMPERSAND) {
761 UnLocked = 0;
762 InsertMode = 0;
763 ResetOiaOnlineA(&OperatorInformationArea);
764 SetOiaTWait(&OperatorInformationArea);
765 SetOiaSystemLocked(&OperatorInformationArea);
766 ResetOiaInsert(&OperatorInformationArea);
767 SetOiaModified();
768 if (c == DISP_AMPERSAND) {
769 TurnOnMdt(i); /* Only for & type */
770 AidByte = AID_ENTER;
771 } else {
772 AidByte = AID_SELPEN;
774 HadAid = 1;
775 SendToIBM();
776 } else {
777 RingBell(
778 "Cursor not in a selectable field (designator)");
781 break;
783 #if !defined(PURE3274)
784 case FCN_ERASE:
785 if (IsProtected(ScreenDec(CursorAddress))) {
786 RingBell("Protected Field");
787 } else {
788 CursorAddress = ScreenDec(CursorAddress);
789 Delete(CursorAddress, ScreenInc(CursorAddress));
791 break;
792 case FCN_WERASE:
793 j = CursorAddress;
794 i = ScreenDec(j);
795 if (IsProtected(i)) {
796 RingBell("Protected Field");
797 } else {
798 SetXIsProtected();
799 while ((!XIsProtected(i) && Disspace(GetHost(i)))
800 && (i != j)) {
801 i = ScreenDec(i);
803 /* we are pointing at a character in a word, or
804 * at a protected position
806 while ((!XIsProtected(i) && !Disspace(GetHost(i)))
807 && (i != j)) {
808 i = ScreenDec(i);
810 /* we are pointing at a space, or at a protected
811 * position
813 CursorAddress = ScreenInc(i);
814 Delete(CursorAddress, j);
816 break;
818 case FCN_FERASE:
819 if (IsProtected(CursorAddress)) {
820 RingBell("Protected Field");
821 } else {
822 CursorAddress = ScreenInc(CursorAddress); /* for btab */
823 BackTab();
824 EraseEndOfField();
826 break;
828 case FCN_RESET:
829 if (InsertMode) {
830 InsertMode = 0;
831 ResetOiaInsert(&OperatorInformationArea);
832 SetOiaModified();
834 break;
835 case FCN_MASTER_RESET:
836 if (InsertMode) {
837 InsertMode = 0;
838 ResetOiaInsert(&OperatorInformationArea);
839 SetOiaModified();
841 RefreshScreen();
842 break;
843 #endif /* !defined(PURE3274) */
845 case FCN_UP:
846 CursorAddress = ScreenUp(CursorAddress);
847 break;
849 case FCN_LEFT:
850 CursorAddress = ScreenDec(CursorAddress);
851 break;
853 case FCN_RIGHT:
854 CursorAddress = ScreenInc(CursorAddress);
855 break;
857 case FCN_DOWN:
858 CursorAddress = ScreenDown(CursorAddress);
859 break;
861 case FCN_DELETE:
862 if (IsProtected(CursorAddress)) {
863 RingBell("Protected Field");
864 } else {
865 Delete(CursorAddress, ScreenInc(CursorAddress));
867 break;
869 case FCN_INSRT:
870 InsertMode = !InsertMode;
871 if (InsertMode) {
872 SetOiaInsert(&OperatorInformationArea);
873 } else {
874 ResetOiaInsert(&OperatorInformationArea);
876 SetOiaModified();
877 break;
879 case FCN_HOME:
880 Home();
881 break;
883 case FCN_NL:
884 /* The algorithm is to look for the first unprotected
885 * column after column 0 of the following line. Having
886 * found that unprotected column, we check whether the
887 * cursor-address-at-entry is at or to the right of the
888 * LeftMargin AND the LeftMargin column of the found line
889 * is unprotected. If this conjunction is true, then
890 * we set the found pointer to the address of the LeftMargin
891 * column in the found line.
892 * Then, we set the cursor address to the found address.
894 i = SetBufferAddress(ScreenLine(ScreenDown(CursorAddress)), 0);
895 j = ScreenInc(WhereAttrByte(CursorAddress));
896 do {
897 if (IsUnProtected(i)) {
898 break;
900 /* Again (see comment in Home()), this COULD be a problem
901 * with an unformatted screen.
903 /* If there was a field with only an attribute byte,
904 * we may be pointing to the attribute byte of the NEXT
905 * field, so just look at the next byte.
907 if (IsStartField(i)) {
908 i = ScreenInc(i);
909 } else {
910 i = ScreenInc(FieldInc(i));
912 } while (i != j);
913 if (!IsUnProtected(i)) { /* couldn't find unprotected */
914 i = SetBufferAddress(0,0);
916 if (OptLeftMargin <= ScreenLineOffset(CursorAddress)) {
917 if (IsUnProtected(SetBufferAddress(ScreenLine(i),
918 OptLeftMargin))) {
919 i = SetBufferAddress(ScreenLine(i), OptLeftMargin);
922 CursorAddress = i;
923 break;
925 case FCN_EINP:
926 if (!FormattedScreen()) {
927 i = CursorAddress;
928 TurnOffMdt(i);
929 do {
930 AddHost(i, 0);
931 i = ScreenInc(i);
932 } while (i != CursorAddress);
933 } else {
935 * The algorithm is: go through each unprotected
936 * field on the screen, clearing it out. When
937 * we are at the start of a field, skip that field
938 * if its contents are protected.
940 i = j = FieldInc(CursorAddress);
941 do {
942 if (IsUnProtected(ScreenInc(i))) {
943 i = ScreenInc(i);
944 TurnOffMdt(i);
945 do {
946 AddHost(i, 0);
947 i = ScreenInc(i);
948 } while (!IsStartField(i));
949 } else {
950 i = FieldInc(i);
952 } while (i != j);
954 Home();
955 break;
957 case FCN_EEOF:
958 EraseEndOfField();
959 break;
961 case FCN_SPACE:
962 OneCharacter(DISP_BLANK, InsertMode); /* Add cent */
963 break;
965 case FCN_CENTSIGN:
966 OneCharacter(DISP_CENTSIGN, InsertMode); /* Add cent */
967 break;
969 case FCN_FM:
970 OneCharacter(DISP_FM, InsertMode); /* Add field mark */
971 break;
973 case FCN_DP:
974 if (IsProtected(CursorAddress)) {
975 RingBell("Protected Field");
976 } else {
977 OneCharacter(DISP_DUP, InsertMode);/* Add dup character */
978 Tab();
980 break;
982 case FCN_TAB:
983 Tab();
984 break;
986 case FCN_BTAB:
987 BackTab();
988 break;
990 #ifdef NOTUSED /* Actually, this is superseded by unix flow
991 * control.
993 case FCN_XOFF:
994 Flow = 0; /* stop output */
995 break;
997 case FCN_XON:
998 if (!Flow) {
999 Flow = 1; /* turn it back on */
1000 DoTerminalOutput();
1002 break;
1003 #endif /* NOTUSED */
1005 #if !defined(PURE3274)
1006 case FCN_ESCAPE:
1007 /* FlushChar(); do we want to flush characters from before? */
1008 StopScreen(1);
1009 command(0, NULL, 0);
1010 if (shell_active == 0) {
1011 ConnectScreen();
1013 break;
1015 case FCN_DISC:
1016 StopScreen(1);
1017 suspend(0, NULL);
1018 setconnmode(0);
1019 ConnectScreen();
1020 break;
1022 case FCN_RESHOW:
1023 RefreshScreen();
1024 break;
1026 case FCN_SETTAB:
1027 OptColTabs[ScreenLineOffset(CursorAddress)] = 1;
1028 break;
1030 case FCN_DELTAB:
1031 OptColTabs[ScreenLineOffset(CursorAddress)] = 0;
1032 break;
1035 * Clear all tabs, home line, and left margin.
1037 case FCN_CLRTAB:
1038 for (i = 0; i < sizeof OptColTabs; i++) {
1039 OptColTabs[i] = 0;
1041 OptHome = 0;
1042 OptLeftMargin = 0;
1043 break;
1045 case FCN_COLTAB:
1046 ColTab();
1047 break;
1049 case FCN_COLBAK:
1050 ColBak();
1051 break;
1053 case FCN_INDENT:
1054 ColTab();
1055 OptLeftMargin = ScreenLineOffset(CursorAddress);
1056 break;
1058 case FCN_UNDENT:
1059 ColBak();
1060 OptLeftMargin = ScreenLineOffset(CursorAddress);
1061 break;
1063 case FCN_SETMRG:
1064 OptLeftMargin = ScreenLineOffset(CursorAddress);
1065 break;
1067 case FCN_SETHOM:
1068 OptHome = ScreenLine(CursorAddress);
1069 break;
1072 * Point to first character of next unprotected word on
1073 * screen.
1075 case FCN_WORDTAB:
1076 i = CursorAddress;
1077 SetXIsProtected();
1078 while (!XIsProtected(i) && !Disspace(GetHost(i))) {
1079 i = ScreenInc(i);
1080 if (i == CursorAddress) {
1081 break;
1084 /* i is either protected, a space (blank or null),
1085 * or wrapped
1087 while (XIsProtected(i) || Disspace(GetHost(i))) {
1088 i = ScreenInc(i);
1089 if (i == CursorAddress) {
1090 break;
1093 CursorAddress = i;
1094 break;
1096 case FCN_WORDBACKTAB:
1097 i = ScreenDec(CursorAddress);
1098 SetXIsProtected();
1099 while (XIsProtected(i) || Disspace(GetHost(i))) {
1100 i = ScreenDec(i);
1101 if (i == CursorAddress) {
1102 break;
1105 /* i is pointing to a character IN an unprotected word
1106 * (or i wrapped)
1108 while (!Disspace(GetHost(i))) {
1109 i = ScreenDec(i);
1110 if (i == CursorAddress) {
1111 break;
1114 CursorAddress = ScreenInc(i);
1115 break;
1117 /* Point to last non-blank character of this/next
1118 * unprotected word.
1120 case FCN_WORDEND:
1121 i = ScreenInc(CursorAddress);
1122 SetXIsProtected();
1123 while (XIsProtected(i) || Disspace(GetHost(i))) {
1124 i = ScreenInc(i);
1125 if (i == CursorAddress) {
1126 break;
1129 /* we are pointing at a character IN an
1130 * unprotected word (or we wrapped)
1132 while (!Disspace(GetHost(i))) {
1133 i = ScreenInc(i);
1134 if (i == CursorAddress) {
1135 break;
1138 CursorAddress = ScreenDec(i);
1139 break;
1141 /* Get to last non-blank of this/next unprotected
1142 * field.
1144 case FCN_FIELDEND:
1145 i = LastOfField(CursorAddress);
1146 if (i != CursorAddress) {
1147 CursorAddress = i; /* We moved; take this */
1148 } else {
1149 j = FieldInc(CursorAddress); /* Move to next field */
1150 i = LastOfField(j);
1151 if (i != j) {
1152 CursorAddress = i; /* We moved; take this */
1154 /* else - nowhere else on screen to be; stay here */
1156 break;
1157 #endif /* !defined(PURE3274) */
1159 default:
1160 /* We don't handle this yet */
1161 RingBell("Function not implemented");
1164 return 1; /* We did something! */
1169 * We get data from the terminal. We keep track of the shift state
1170 * (including ALT, CONTROL), and then call AcceptKeystroke to actually
1171 * process any non-shift keys.
1175 DataFrom3270(buffer, count)
1176 unsigned char *buffer; /* where the data is */
1177 int count; /* how much data there is */
1179 int origCount;
1181 origCount = count;
1183 while (count) {
1184 if (*buffer >= numberof(hits)) {
1185 ExitString("Unknown scancode encountered in DataFrom3270.\n", 1);
1186 /*NOTREACHED*/
1189 switch (hits[*buffer].hit[HITNUM(rememberedshiftstate)].ctlrfcn) {
1191 case FCN_MAKE_SHIFT:
1192 rememberedshiftstate |= (SHIFT_RIGHT|SHIFT_UPSHIFT);
1193 break;
1194 case FCN_BREAK_SHIFT:
1195 rememberedshiftstate &= ~(SHIFT_RIGHT|SHIFT_UPSHIFT);
1196 break;
1197 case FCN_MAKE_ALT:
1198 rememberedshiftstate |= SHIFT_ALT;
1199 break;
1200 case FCN_BREAK_ALT:
1201 rememberedshiftstate &= ~SHIFT_ALT;
1202 break;
1203 default:
1204 if (AcceptKeystroke(*buffer, rememberedshiftstate) == 0) {
1205 return(origCount-count);
1207 break;
1209 buffer++;
1210 count--;
1212 return(origCount-count);