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