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