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