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,&reg,&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,&reg,&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,&reg,&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,&reg,&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,&reg,&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,&reg,&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,&reg,&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