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