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