1 /* ******************************************** 2 * * 3 * Copyright, (C) Honeywell Bull Inc., 1988 * 4 * * 5 ******************************************** */ 6 7 /* HISTORY COMMENTS: 8 1) change(88-04-29,Lee), approve(88-05-16,MCR7897), audit(88-09-19,Flegel), 9 install(88-10-12,MR12.2-1160): 10 Created. 11 2) change(88-07-25,Lee), approve(88-05-16,MCR7897), audit(88-09-19,Flegel), 12 install(88-10-12,MR12.2-1160): 13 Documentation additions only. Added header comments to all routines. 14 3) change(88-08-09,Lee), approve(88-05-16,MCR7897), audit(88-09-19,Flegel), 15 install(88-10-12,MR12.2-1160): 16 Fix references to include files; "wstdefs.h" was split into 17 "wstdefs.h" and "wsttype.h" to avoid declaration clash; also, 18 various constants defined to descriptive names. 19 4) change(89-01-30,Lee), approve(89-01-02,MCR8043), audit(89-03-14,Flegel), 20 install(89-04-24,MR12.3-1033): 21 Separated input and output arguments to int86() to avoid confusion 22 when parameters are used. 23 END HISTORY COMMENTS */ 24 25 /* WSTSCRN - This module contains routines for manipulating WSTERM's 26 various screens. The copy of what should be contained on the screen 27 is maintained in screen buffers which may be "swapped" to the screen. 28 */ 29 30 #include <dos.h> 31 #include <ctype.h> 32 #include "wstdefs.h" 33 #include "wstglob.h" 34 35 /*^L 36 ********************************************************************** 37 38 Routine: WST_SCREEN_CLEAR 39 40 Function: 41 This routine blank fills the contents of a specified screen 42 buffer and initializes its cursor coordinates to the home position. 43 44 Parameters: 45 (output) scr - pointer to the screen buffer to clear 46 47 Returns: NONE 48 49 **********************************************************************/ 50 51 wst_screen_clear(scr) 52 SCREEN *scr; /* pointer to screen buffer */ 53 { 54 int i; 55 56 /* home cursor position */ 57 scr->cursor_row = CURSOR_HOME_ROW; 58 scr->cursor_col = CURSOR_HOME_COL; 59 60 /* clear the screen by writing blanks to entire screen buffer */ 61 for (i = 0; i < SCREEN_BUFFER_BYTES;) { 62 scr->screen[i++] = ' '; 63 scr->screen[i++] = scr->attr; 64 } 65 } 66 67 68 69 /*^L 70 ********************************************************************** 71 72 Routine: WST_SCREEN_PRINTLINE 73 74 Function: 75 This routine writes a line of text to the screen buffer at the 76 screen buffer's current row coordinate. The screen buffer's row 77 coordinate variable is then incremented. 78 79 Parameters: 80 (output) scr - pointer to the screen buffer to write the 81 string to 82 (input) str - the character string to write 83 84 Returns: NONE 85 86 **********************************************************************/ 87 88 wst_screen_printline(scr,str) 89 SCREEN *scr; /* pointer to screen buffer */ 90 char *str; /* string to write to screen buffer */ 91 { 92 register int col; 93 register int offset; 94 95 /* write the string at the cursor line starting at column 0 */ 96 col = 0; 97 98 /* index into appropriate location into screen buffer */ 99 /* (multiply by 2 to account for character and attribute bytes) */ 100 offset = scr->cursor_row * SCREEN_COLS * 2; 101 102 /* put each character to the screen buffer until end of string */ 103 /* or until end of line */ 104 for (col = 0; *str && col < SCREEN_COLS; col++) { 105 scr->screen[offset++] = *str++; 106 offset++; 107 } 108 109 /* increment the cursor line */ 110 scr->cursor_row++; 111 } 112 113 114 115 /*^L 116 ********************************************************************** 117 118 Routine: PUT_WST_SCREEN 119 120 Function: 121 This routine displays a character, updating the position of the 122 physical cursor in the cursor position variables of the specified 123 screen buffer. Boundary checks are made to ensure that the cursor 124 stays within the defined screen boundary. 125 126 Parameters: 127 (output) scr - specifies the screen buffer whose cursor 128 coordinate variables are to be updated 129 (input) ch - specifies the character to display 130 131 Returns: NONE 132 133 **********************************************************************/ 134 135 put_wst_screen(scr,ch) 136 SCREEN *scr; /* pointer to screen buffer */ 137 int ch; /* character to */ 138 { 139 140 /* save current cursor position */ 141 cursor_pos(&scr->cursor_row,&scr->cursor_col); 142 143 /* overwriting status line? */ 144 if (scr->cursor_row > MAX_SCREEN_LINE) { 145 146 /* scroll the display */ 147 wst_scroll(); 148 149 /* "scroll" cursor as well */ 150 scr->cursor_row = MAX_SCREEN_LINE; 151 cursor_move(scr->cursor_row,scr->cursor_col); 152 } 153 154 /* display the character */ 155 putch(ch); 156 157 /* get cursor position */ 158 cursor_pos(&scr->cursor_row,&scr->cursor_col); 159 160 /* on status line? */ 161 if (scr->cursor_row > MAX_SCREEN_LINE) { 162 163 /* scroll display up */ 164 wst_scroll(); 165 166 /* "scroll" cursor up */ 167 scr->cursor_row = MAX_SCREEN_LINE; 168 cursor_move(scr->cursor_row,scr->cursor_col); 169 } 170 } 171 172 173 174 /*^L 175 ********************************************************************** 176 177 Routine: WST_SCREENS_INIT 178 179 Function: 180 This routine initializes wsterm's screen buffers (foreground, 181 background and temporary) when WSTERM starts up. 182 183 Parameters: 184 (input) ch - specifies the character to initialize the 185 contents of the screen buffer with 186 (input) attr - specifies the attribute to initialize 187 the contents of the screen buffer with 188 189 Returns: NONE 190 191 Note 1 - Only the attribute and cursor position fields are 192 initialized for the temporary screen buffer as the screen 193 contents should always be initialized before it is used. 194 **********************************************************************/ 195 196 wst_screens_init(ch,attr) 197 int ch; /* character to fill the screens with on initialization */ 198 int attr; /* attribute to fill the screens with on initialization */ 199 { 200 int i; 201 202 /* set the attribute to be used for a particular screen */ 203 wst_fg_screen.attr = attr; 204 wst_bg_screen.attr = attr; 205 wst_tmp_screen.attr = attr; 206 wst_help_screen.attr = attr; 207 208 /* home the cursor positions */ 209 wst_fg_screen.cursor_row = CURSOR_HOME_ROW; 210 wst_fg_screen.cursor_col = CURSOR_HOME_COL; 211 212 wst_bg_screen.cursor_row = CURSOR_HOME_ROW; 213 wst_bg_screen.cursor_col = CURSOR_HOME_COL; 214 215 wst_tmp_screen.cursor_row = CURSOR_HOME_ROW; 216 wst_tmp_screen.cursor_col = CURSOR_HOME_COL; 217 218 wst_help_screen.cursor_row = CURSOR_HOME_ROW; 219 wst_help_screen.cursor_col = CURSOR_HOME_COL; 220 221 /* initialize the contents of the screens; */ 222 /* temporary and help screen is not initialized, it should be */ 223 /* explicitly initialized each time it is used */ 224 for (i = 0; i < SCREEN_BUFFER_BYTES;) { 225 wst_fg_screen.screen[i] = ch; 226 wst_bg_screen.screen[i++] = ch; 227 wst_fg_screen.screen[i] = attr; 228 wst_bg_screen.screen[i++] = attr; 229 } 230 } 231 232 233 234 /*^L 235 ********************************************************************** 236 237 Routine: SAVE_WST_SCREEN 238 239 Function: 240 This routine saves the contents of the screen and the position 241 of the cursor to a screen buffer structure. 242 243 Parameters: 244 (output) scr - pointer to the screen buffer structure to 245 save the screen to 246 247 Returns: NONE 248 249 Note 1 - Only the first 24 lines are saved as the 25th line is the 250 status line 251 **********************************************************************/ 252 253 save_wst_screen(scr) 254 SCREEN *scr; /* pointer to the screen buffer */ 255 { 256 cursor_pos(&scr->cursor_row,&scr->cursor_col); 257 save_screen(scr->screen); 258 } 259 260 261 262 /*^L 263 ********************************************************************** 264 265 Routine: RESTORE_WST_SCREEN 266 267 Function: 268 This routine restores the contents of the screen and cursor 269 position which was previously saved in a screen buffer structure. 270 271 Parameters: 272 (input) scr - specifies the screen buffer structure to 273 restore the screen from 274 275 Returns: NONE 276 277 Note 1 - Only the first 24 lines of the screen are restored as the 278 25th line is the status line 279 **********************************************************************/ 280 281 restore_wst_screen(scr) 282 SCREEN *scr; 283 { 284 restore_screen(scr->screen); 285 cursor_move(scr->cursor_row,scr->cursor_col); 286 } 287 288 289 290 /*^L 291 ********************************************************************** 292 293 Routine: CURSOR_MOVE 294 295 Function: 296 This routine moves the physical cursor on the screen to a 297 specified screen coordinate. 298 299 Parameters: 300 (input) row - specifies the row to move to (0 = top of 301 screen) 302 (input) col - specifies the column to move to (0 = left 303 most column) 304 305 Returns: NONE 306 307 **********************************************************************/ 308 309 cursor_move(row,col) 310 int row; 311 int col; 312 { 313 union REGS reg, outreg; 314 315 reg.h.ah = VIDEO_CURSOR_MOVE_FUNC; /* VIDEO cursor set */ 316 reg.h.dh = row; /* coordinates to move to */ 317 reg.h.dl = col; 318 reg.h.bh = get_active_page(); /* in current active page */ 319 int86(BIOS_VIDEO,®,&outreg); /* call BIOS routine to do actual move */ 320 } 321 322 323 /*^L 324 ********************************************************************** 325 326 Routine: CURSOR_POS 327 328 Function: 329 This routine reads the coordinates of the physical cursor on 330 the screen. 331 332 Parameters: 333 (output) row - pointer to the integer for passing back 334 the row coordinate of the cursor 335 (output) col - pointer to the integer for passing back 336 the column coordinate of the cursor 337 338 Returns: NONE 339 340 **********************************************************************/ 341 342 cursor_pos(row,col) 343 int *row; 344 int *col; 345 { 346 union REGS reg, outreg; 347 348 reg.h.ah = VIDEO_CURSOR_READ_FUNC; /* VIDEO cursor read */ 349 reg.h.bh = get_active_page(); /* from current active page */ 350 int86(BIOS_VIDEO,®,&outreg); /* call BIOS to get coordinates */ 351 *row = outreg.h.dh; 352 *col = outreg.h.dl; 353 } 354 355 356 357 /*^L 358 ********************************************************************** 359 360 Routine: WAIT_FOR_KEY 361 362 Function: 363 This routine will get a key, waiting blocked if necessary. 364 365 Parameters: NONE 366 367 Returns: an ASCII code if an ASCII keyboard character 368 was pressed 369 an encoded value greater than 255 if a function 370 or ALT key was pressed 371 372 **********************************************************************/ 373 374 wait_for_key() 375 { 376 union REGS reg, outreg; 377 int code; 378 379 /* break key before this routine got called? */ 380 if (break_flag) { 381 break_flag = FALSE; 382 return(BREAK_KEY); 383 } 384 385 /* read the keyboard */ 386 reg.h.ah = BIOS_KB_READ; 387 int86(BIOS_KB,®,&outreg); 388 389 /* break key hit ? */ 390 if (break_flag) { 391 break_flag = FALSE; 392 return(BREAK_KEY); 393 } 394 395 /* non zero indicates regular ASCII character */ 396 if (outreg.h.al) 397 return((int)outreg.h.al); 398 399 /* otherwise extended ASCII code, generate unique extension code */ 400 code = ASCII_EXTEND_CODE + outreg.h.ah; 401 return(code); 402 } 403 404 405 406 407 /*^L 408 ********************************************************************** 409 410 Routine: CHECKKEY 411 412 Function: 413 This routine checks to see if the a keyboard key has already 414 been pressed. 415 416 Parameters: NONE 417 418 Returns: an ASCII code if an ASCII keyboard character 419 was pressed 420 an encoded value greater than 255 if a function 421 or ALT key was pressed 422 -1 if no key was pressed 423 424 **********************************************************************/ 425 426 checkkey() 427 { 428 union REGS reg, outreg; 429 int cpu_flags; 430 431 if (break_flag) /* break key was hit */ 432 return(BREAK_KEY); 433 434 reg.h.ah = BIOS_KB_STATUS; /* call BIOS routine to see if key was hit */ 435 cpu_flags = int86(BIOS_KB,®,&outreg); 436 437 /* check if key was hit */ 438 if (cpu_flags & Z_FLAG_MASK) 439 return(-1); 440 441 /* regular ASCII character? */ 442 if (outreg.h.al) 443 return((int)outreg.h.al); 444 445 /* encode as an extended ASCII value */ 446 return (ASCII_EXTEND_CODE + outreg.h.ah); 447 } 448 449 450 451 /*^L 452 ********************************************************************** 453 454 Routine: ENABLE_CTL_C_CHECK 455 456 Function: 457 This routine turns on CTRL-C checking and saves the original 458 CTRL-C checking status (either enabled or disabled) in the global 459 variable 'orig_break_status'. 460 461 Parameters: NONE 462 463 Returns: NONE 464 465 **********************************************************************/ 466 467 enable_ctl_c_check() 468 { 469 union REGS reg, outreg; 470 471 reg.h.ah = DOS_CTRL_C_FUNCTION; /* function to get/set ctrl-c checking */ 472 473 /* exchange current CTRL-C checking state (enabled or disabled) 474 with ENABLED state 475 */ 476 reg.h.al = DOS_CTRL_C_EXCHANGE; /* exchange states */ 477 reg.h.dl = DOS_CTRL_C_ENABLE; /* checking enabled after exchange */ 478 479 int86(DOS_INT,®,&outreg); /* call DOS interrupt to set ctrl-c checking */ 480 orig_break_status = outreg.h.dl; /* save original ctrl-c checking status */ 481 } 482 483 484 485 /*^L 486 ********************************************************************** 487 488 Routine: RESTORE_CTL_C_CHECK 489 490 Function: 491 This routine restores CTRL-C checking to the state (enabled or 492 disabled) previously saved in the global variable 493 'orig_break_status'. 494 495 Parameters: NONE 496 497 Returns: NONE 498 499 **********************************************************************/ 500 501 restore_ctl_c_check() 502 { 503 union REGS reg, outreg; 504 505 /* if originally ON, then no need to turn OFF ctl-c checking */ 506 if (orig_break_status) return; 507 508 /* turn off ctl-c checking */ 509 reg.h.ah = DOS_CTRL_C_FUNCTION; /* function to get/set ctrl-c checking */ 510 reg.h.al = DOS_CTRL_C_SET; /* switch to set ctrl-c checking */ 511 reg.h.dl = DOS_CTRL_C_DISABLE; /* indicate ctrl-c checking turned off */ 512 int86(DOS_INT,®,&outreg); /* call BIOS to turn ctrl-c checking off */ 513 } 514 515 516 517 /*^L 518 ********************************************************************** 519 520 Routine: PUT_TO_SCREEN 521 522 Function: 523 This routine displays a character to the screen with boundary 524 checking. If the character goes beyond the defined screen size, the 525 cursor is forced back inside the screen area. In particular, this 526 ensures that no character, be it part of a long string or escape 527 sequence, will be placed outside the defined screen area. 528 529 Parameters: 530 (input) ch - specifies the character to display; the 531 character to passed to the screen driver 532 533 Returns: NONE 534 535 **********************************************************************/ 536 537 put_to_screen(ch) 538 int ch; 539 { 540 union REGS reg, outreg; 541 542 /* save current cursor coordinates; assume in foreground */ 543 cursor_pos(&wst_fg_screen.cursor_row,&wst_fg_screen.cursor_col); 544 545 /* cursor already out of bounds? */ 546 if (wst_fg_screen.cursor_row > MAX_SCREEN_LINE) { 547 548 /* "scroll" cursor up */ 549 wst_fg_screen.cursor_row = MAX_SCREEN_LINE; 550 cursor_move(wst_fg_screen.cursor_row,wst_fg_screen.cursor_col); 551 } 552 553 /* display the character */ 554 reg.h.al = ch; 555 int86(0x29,®,&outreg); 556 557 /* check again */ 558 cursor_pos(&wst_fg_screen.cursor_row,&wst_fg_screen.cursor_col); 559 560 if (wst_fg_screen.cursor_row > MAX_SCREEN_LINE) { 561 562 /* "scroll" cursor up */ 563 wst_fg_screen.cursor_row = MAX_SCREEN_LINE; 564 cursor_move(wst_fg_screen.cursor_row,wst_fg_screen.cursor_col); 565 } 566 } 567 568 569 570 /*^L 571 ********************************************************************** 572 573 Routine: WST_GETLINE 574 575 Function: 576 This routine will get a line of input from the keyboard. The 577 line is terminated when the user hits <CARRIAGE RETURN>. This 578 routine is used instead of gets() to prevent ^C from breaking out 579 of the program. 580 581 Parameters: 582 (output) scr - pointer to the screen buffer to use for 583 saving cursor position information; while 584 in background screen, background screen 585 buffer is used; if in foreground screen, 586 foreground screen buffer should be used 587 (output) str - specifies the string for passing back the 588 line entered 589 590 Returns: NONE 591 592 **********************************************************************/ 593 594 wst_getline(scr,str,stat_line) 595 SCREEN *scr; 596 char *str; /* string to pass back the value entered */ 597 char *stat_line; /* status line message being displayed */ 598 { 599 int ch; 600 int i; /* index to where data is to be placed in string */ 601 602 i = 0; 603 604 /* loop until <RETURN> hit */ 605 while ((ch = getkey(BLOCK)) != RETURN_KEY) { 606 607 /* check BACKSPACE key */ 608 if (ch == BACKSPACE) { 609 610 /* only if something exists in the string */ 611 if (i > ZERO_INDEX_VALUE) { 612 /* decrement index */ 613 i--; 614 615 /* rubout the character displayed */ 616 put_wst_screen(scr,BACKSPACE); 617 put_wst_screen(scr,' '); 618 put_wst_screen(scr,BACKSPACE); 619 } 620 } 621 622 /* invoke background help */ 623 else if (ch == ALT_H) { 624 help(BG_HELP); 625 status_line(stat_line); 626 } 627 628 /* if is a printable character and line length of 127 not exceeded */ 629 else if (i < 127 && ch < ASCII_DEL && isprint(ch)) { 630 631 /* add character to string */ 632 str[i] = ch; 633 i++; 634 635 /* display the character */ 636 put_wst_screen(scr,ch); 637 } 638 639 else 640 beep(); 641 } 642 643 /* echo the linefeed at end of line */ 644 put_wst_screen(scr,'\n'); 645 646 /* terminate the string */ 647 str[i] = NUL_TERMINATOR; 648 } 649 650 651 652 /*^L 653 ********************************************************************** 654 655 Routine: INIT_WST_SCROLL 656 657 Function: 658 This function initializes a global structure "scroll_regs" 659 which is used for scrolling the working area (first 24 lines) 660 of the screen. 661 662 Parameters: NONE 663 664 Returns: NONE 665 666 **********************************************************************/ 667 668 init_wst_scroll(attr) 669 int attr; 670 { 671 /* scroll display up */ 672 scroll_regs.h.ah = VIDEO_SCROLL_UP_FUNC; 673 scroll_regs.h.al = DEFAULT_LINES_TO_SCROLL; 674 scroll_regs.h.ch = CURSOR_HOME_ROW; 675 scroll_regs.h.cl = CURSOR_HOME_COL; 676 scroll_regs.h.dh = SCREEN_LINES-1; 677 scroll_regs.h.dl = SCREEN_COLS-1; 678 scroll_regs.h.bh = attr; 679 } 680 681 682 683 /*^L 684 ********************************************************************** 685 686 Routine: WST_SCROLL 687 688 Function: 689 This function scrolls the first 24 lines of the screen up a 690 row, filling the 24th row with blanks. 691 692 Parameters: NONE 693 694 Returns: NONE 695 696 **********************************************************************/ 697 698 wst_scroll() 699 { 700 union REGS out; 701 702 /* scroll display up */ 703 int86(BIOS_VIDEO,&scroll_regs,&out); 704 } 705 706 707 708 /*^L 709 ********************************************************************** 710 711 Routine: PUT_SCREEN_STR 712 713 Function: 714 This routine write a string directly to the screen driver. 715 716 Parameters: 717 (input) str - pointer to the string to write 718 719 Returns: NONE 720 721 **********************************************************************/ 722 723 put_screen_str(str) 724 char *str; 725 { 726 while (*str) putch(*str++); 727 } 728 729 730 731 /*^L 732 ********************************************************************** 733 734 Routine: UPPERCASE 735 736 Function: 737 This routine returns the uppercased ASCII value of a character 738 if that character is a lowercased letter. This function is used 739 instead of the normal ctype.h toupper() because the character may 740 be an extended ASCII value, i.e. the value of the character is not 741 restricted to be in the range of 0 to 127. 742 743 Parameters: 744 (input) ch - the character to convert to uppercase 745 746 Returns: the value of 'ch' if 'ch' is not a lowercase 747 letter; 748 otherwise the uppercase value of 'ch' 749 750 **********************************************************************/ 751 752 uppercase(ch) 753 int ch; 754 { 755 if (ch < 'a' || ch > 'z') return(ch); 756 return(ch - ('a' - 'A')); 757 } 758 759 760 761 /*^L 762 ********************************************************************** 763 764 Routine: WST_RESET 765 766 Function: 767 This function handles the reset escape sequence "ESC c" which 768 causes the colors, scrolling region and other screen attributes to 769 be reset. This routine restores the attributes needed by WSTERM 770 after the reset and updates variables which are affected by the 771 reset. 772 773 Parameters: NONE 774 775 Returns: NONE 776 777 **********************************************************************/ 778 779 wst_reset() 780 { 781 int attr; 782 783 /* update attributes of screen */ 784 getattr(&attr); 785 wst_fg_screen.attr = attr; 786 wst_bg_screen.attr = attr; 787 wst_tmp_screen.attr = attr; 788 wst_help_screen.attr = attr; 789 scroll_regs.h.bh = attr; 790 791 /* restore status line and WSTERM version */ 792 update_status(); 793 clear_screen (); 794 cursor_move (CURSOR_HOME_ROW, 60); 795 putscr("WSTERM Vers ",12); 796 putscr(version,strlen(version)); 797 cursor_move (CURSOR_HOME_ROW,CURSOR_HOME_COL); 798 799 /* tell edit mode that screen has been cleared/reset */ 800 if (edlin.length > 0) 801 erase_edit_line(&edlin); 802 edlin.orig_row = edlin.cur_row = edlin.max_row = CURSOR_HOME_ROW; 803 edlin.orig_col = edlin.cur_col = edlin.cur_row = CURSOR_HOME_COL; 804 805 } 806