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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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