1 /*
2  * The routines in this file provide support for the IBM-PC and other
3  * compatible terminals. It goes directly to the graphics RAM to do
4  * screen output. It compiles into nothing if not an IBM-PC driver
5  * Supported monitor cards include CGA, MONO and EGA.
6  */
7 
8 #define	termdef	1			/* don't define "term" external */
9 
10 #include        <stdio.h>
11 #include	"estruct.h"
12 #include	"eproto.h"
13 #include        "edef.h"
14 #include	"elang.h"
15 
16 #if     IBMPC
17 #define NROW	50			/* Max Screen size.		*/
18 #define NCOL    80                      /* Edit if you want to.         */
19 #define	MARGIN	8			/* size of minimim margin and	*/
20 #define	SCRSIZ	64			/* scroll size for extended lines */
21 #define	NPAUSE	200			/* # times thru update to pause */
22 #define BEL     0x07                    /* BEL character.               */
23 #define ESC     0x1B                    /* ESC character.               */
24 #define	SPACE	32			/* space character		*/
25 
26 #define	SCADC	0xb8000000L		/* CGA address of screen RAM	*/
27 #define	SCADM	0xb0000000L		/* MONO address of screen RAM	*/
28 #define SCADE	0xb8000000L		/* EGA/VGA address of screen RAM*/
29 
30 #define MONOCRSR 0x0B0D			/* monochrome cursor		*/
31 #define CGACRSR 0x0607			/* CGA cursor			*/
32 #define EGACRSR 0x0709			/* EGA/VGA cursor		*/
33 
34 #define	CDCGA	0			/* color graphics card		*/
35 #define	CDMONO	1			/* monochrome text card		*/
36 #define	CDEGA	2			/* EGA color adapter		*/
37 #define	CDVGA	3			/* VGA color adapter		*/
38 #define	CDVGA12	4			/* VGA 12 line mode		*/
39 #define	CDCGA40	5			/* CGA 40 wide mode		*/
40 #define	CDSENSE	9			/* detect the card type		*/
41 
42 #define NDRIVE	6			/* number of screen drivers	*/
43 
44 typedef struct sdrive {
45 	char drv_name[8];		/* screen driver name	*/
46 	long drv_scradd;		/* address of segment of screen ram */
47 	int drv_rows;			/* # of rows for screen driver */
48 	int drv_cols;			/* # of columns for screen driver */
49 } SDRIVE;
50 
51 SDRIVE scr_drive[] = {
52 	"CGA",   SCADC, 25, 80,		/* standard color card		*/
53 	"MONO",  SCADM, 25, 80,		/* momochrome graphics adapter	*/
54 	"EGA",   SCADE, 43, 80,		/* Enhanced graphics adapter	*/
55 	"VGA",   SCADE, 50, 80,		/* Very Enhanced graphics adapter*/
56 	"VGA12", SCADE, 12, 80,		/* 12 lines x 80 cols		*/
57 	"CGA40", SCADC, 25, 40,		/* low resolution CGA		*/
58 };
59 
60 int dtype = -1;				/* current display type		*/
61 
62 long scadd;				/* address of screen ram	*/
63 int *scptr[NROW];			/* pointer to screen lines	*/
64 unsigned int sline[NCOL];		/* screen line image		*/
65 int num_cols;				/* current number of columns	*/
66 int orig_mode;				/* screen mode on entry		*/
67 int egaexist = FALSE;			/* is an EGA card available?	*/
68 int vgaexist = FALSE;			/* is video graphics array available? */
69 extern union REGS rg;			/* cpu register for use of DOS calls */
70 int revflag = FALSE;			/* are we currently in rev video? */
71 int desk_rows;				/* number of rows on current desktop */
72 int desk_cols;				/* number of cols on current desktop */
73 int break_flag;			/* state of MSDOS control break processing */
74 
75 int PASCAL NEAR ibmmove();
76 int PASCAL NEAR ibmeeol();
77 int PASCAL NEAR ibmputc();
78 int PASCAL NEAR ibmeeop();
79 int PASCAL NEAR ibmclrdesk();
80 int PASCAL NEAR ibmrev();
81 int PASCAL NEAR ibmcres();
82 int PASCAL NEAR spal();
83 int PASCAL NEAR ibmbeep();
84 int PASCAL NEAR ibmopen();
85 int PASCAL NEAR ibmclose();
86 int PASCAL NEAR ibmkopen();
87 int PASCAL NEAR ibmkclose();
88 int PASCAL NEAR scinit();
89 int PASCAL NEAR screen_init();
90 int PASCAL NEAR getboard();
91 int PASCAL NEAR egaopen();
92 int PASCAL NEAR egaclose();
93 int PASCAL NEAR cga40_open();
94 int PASCAL NEAR cga40_close();
95 int PASCAL NEAR change_width();
96 int PASCAL NEAR fnclabel();
97 
98 #if	COLOR
99 int PASCAL NEAR ibmfcol();
100 int PASCAL NEAR ibmbcol();
101 int	cfcolor = -1;		/* current forground color */
102 int	cbcolor = -1;		/* current background color */
103 int	ctrans[] =		/* ansi to ibm color translation table */
104 	{0, 4, 2, 6, 1, 5, 3, 7,
105 	 8, 12, 10, 14, 9, 13, 11, 15};
106 #endif
107 
108 /*
109  * Standard terminal interface dispatch table. Most of the fields point into
110  * "termio" code.
111  */
112 TERM    term    = {
113 	NROW-1,
114         NROW-1,
115         NCOL,
116         NCOL,
117 	0, 0,
118 	MARGIN,
119 	SCRSIZ,
120 	NPAUSE,
121         ibmopen,
122         ibmclose,
123 	ibmkopen,
124 	ibmkclose,
125         ttgetc,
126 	ibmputc,
127         ttflush,
128         ibmmove,
129         ibmeeol,
130         ibmeeop,
131         ibmclrdesk,
132         ibmbeep,
133 	ibmrev,
134 	ibmcres
135 #if	COLOR
136 	, ibmfcol,
137 	ibmbcol
138 #endif
139 };
140 
141 #if	COLOR
ibmfcol(color)142 int PASCAL NEAR ibmfcol(color)	/* set the current output color */
143 
144 int color;	/* color to set */
145 
146 {
147 	cfcolor = ctrans[color];
148 }
149 
ibmbcol(color)150 int PASCAL NEAR ibmbcol(color)	/* set the current background color */
151 
152 int color;	/* color to set */
153 
154 {
155         cbcolor = ctrans[color];
156 }
157 #endif
158 
ibmmove(row,col)159 int PASCAL NEAR ibmmove(row, col)
160 {
161 	rg.h.ah = 2;		/* set cursor position function code */
162 	rg.h.dl = col + term.t_colorg;
163 	rg.h.dh = row + term.t_roworg;
164 	rg.h.bh = 0;		/* set screen page number */
165 	int86(0x10, &rg, &rg);
166 }
167 
ibmeeol()168 int PASCAL NEAR ibmeeol()	/* erase to the end of the line */
169 
170 {
171 	unsigned int attr;	/* attribute byte mask to place in RAM */
172 	unsigned int *lnptr;	/* pointer to the destination line */
173 	int i;
174 	int ccol;	/* current column cursor lives */
175 	int crow;	/*	   row	*/
176 
177 	/* find the current cursor position */
178 	rg.h.ah = 3;		/* read cursor position function code */
179 	rg.h.bh = 0;		/* current video page */
180 	int86(0x10, &rg, &rg);
181 	ccol = rg.h.dl - term.t_colorg;	/* record current column */
182 	crow = rg.h.dh - term.t_roworg;	/* and row */
183 
184 	/* build the attribute byte and setup the screen pointer */
185 #if	COLOR
186 	if (dtype != CDMONO)
187 		if (revflag)
188 			attr = (((cfcolor & 15) << 4) | (cbcolor & 15)) << 8;
189 		else
190 			attr = (((cbcolor & 15) << 4) | (cfcolor & 15)) << 8;
191 	else
192 		if (revflag)
193 			attr = 0x7000;
194 		else
195 			attr = 0x0700;
196 #else
197 	attr = 0x0700;
198 #endif
199 	lnptr = &sline[0];
200 	for (i=0; i < term.t_ncol; i++)
201 		*lnptr++ = SPACE | attr;
202 
203 	if (flickcode && (dtype == CDCGA || dtype == CDCGA40)) {
204 		/* wait for vertical retrace to be off */
205 		while ((inp(0x3da) & 8))
206 			;
207 
208 		/* and to be back on */
209 		while ((inp(0x3da) & 8) == 0)
210 			;
211 	}
212 
213 	/* and send the string out */
214 	movmem(&sline[0], scptr[crow+term.t_roworg]+ccol+term.t_colorg, (term.t_ncol-ccol)*2);
215 }
216 
ibmputc(ch)217 int PASCAL NEAR ibmputc(ch) /* put a character at the current position in the
218 		   current colors */
219 
220 int ch;
221 
222 {
223 	/* if its a newline, we have to move the cursor */
224 	if (ch == '\n' || ch == '\r') {
225 		rg.h.ah = 3;
226 		int86(0x10, &rg, &rg);
227 		if (rg.h.dh == 24) {
228 			ibmmove(20, 0);
229 			/* we must scroll the screen */
230 			rg.h.ah = 6;	/* scroll up */
231 			rg.h.al = 1;	/* # of lines to scroll by */
232 #if	COLOR
233 			rg.h.bh = cfcolor; /* attribute for blank line */
234 #else
235 			rg.h.bh = 0; /* attribute for blank line */
236 #endif
237 			rg.x.cx = 0;	/* upper left corner of scroll */
238 			rg.x.dx = 0x184f;/* lower right */
239 			int86(0x10, &rg, &rg);
240 			rg.h.dh = 23;
241 		}
242 		ibmmove(rg.h.dh + 1, 0);
243 		return(TRUE);
244 	}
245 
246 #if	1
247 	if (ch == '\b') {
248 
249 		/* backup the cursor by 1 position */
250 		rg.h.ah = 3;		/* read current position */
251 		int86(0x10, &rg, &rg);
252 		rg.h.dl--;		/* move it forward one */
253 		rg.h.ah = 2;		/* set its new position */
254 		int86(0x10, &rg, &rg);
255 
256 		rg.h.ah = 9;		/* write char with attributes to cursor position */
257 		rg.h.bh = 0;		/* display page zero */
258 		rg.x.cx = 1;		/* only one please! */
259 		rg.h.al = ' ';		/* character to write */
260 #if	COLOR
261 		rg.h.bl = ((ctrans[gbcolor] << 4) | ctrans[gfcolor]);/* attribute */
262 #else
263 		rg.h.bl = 07;
264 #endif
265 		int86(0x10, &rg, &rg);
266 		return(TRUE);
267 	}
268 
269 	if (ch == 7) {
270 		TTbeep();
271 		return(TRUE);
272 	}
273 
274 	rg.h.ah = 9;		/* write char with attributes to cursor position */
275 	rg.h.bh = 0;		/* display page zero */
276 	rg.x.cx = 1;		/* only one please! */
277 	rg.h.al = ch;		/* character to write */
278 #if	COLOR
279 	rg.h.bl = ((ctrans[gbcolor] << 4) | ctrans[gfcolor]);	/* attribute */
280 #else
281 	rg.h.bl = 07;
282 #endif
283 	int86(0x10, &rg, &rg);
284 
285 	/* advance the cursor by 1 position */
286 	rg.h.ah = 3;		/* read current position */
287 	int86(0x10, &rg, &rg);
288 	rg.h.dl++;		/* move it forward one */
289 	rg.h.ah = 2;		/* set its new position */
290 	int86(0x10, &rg, &rg);
291 #else
292 	rg.h.ah = 14;		/* write char to screen with current attrs */
293 	rg.h.al = ch;
294 #if	COLOR
295 	if (dtype != CDMONO)
296 		rg.h.bl = cfcolor;
297 	else
298 		rg.h.bl = 0x07;
299 #else
300 	rg.h.bl = 0x07;
301 #endif
302 	int86(0x10, &rg, &rg);
303 #endif
304 }
305 
ibmeeop()306 int PASCAL NEAR ibmeeop()
307 
308 {
309 	rg.h.ah = 6;		/* scroll page up function code */
310 	rg.h.al = 0;		/* # lines to scroll (clear it) */
311 	rg.x.cx = (term.t_roworg << 8) | (term.t_colorg);
312 				/* upper left corner of scroll */
313 	rg.x.dx = ((term.t_nrow + term.t_roworg) << 8) |
314 			(term.t_ncol + term.t_colorg - 1);
315 				/* lower right corner of scroll */
316 #if	COLOR
317 	if (dtype != CDMONO)
318 		if (revflag)
319 			rg.h.bh = ((ctrans[gfcolor] & 15) << 4) | (ctrans[gbcolor] & 15);
320 		else
321 			rg.h.bh = ((ctrans[gbcolor] & 15) << 4) | (ctrans[gfcolor] & 15);
322 	else
323 		if (revflag)
324 			rg.h.bh = 70;
325 		else
326 			rg.h.bh = 07;
327 #else
328 	rg.h.bh = 07;
329 #endif
330 	int86(0x10, &rg, &rg);
331 }
332 
ibmclrdesk()333 int PASCAL NEAR ibmclrdesk()
334 
335 {
336 	int attr;		/* attribute to fill screen with */
337 
338 	rg.h.ah = 6;		/* scroll page up function code */
339 	rg.h.al = 0;		/* # lines to scroll (clear it) */
340 	rg.x.cx = 0;		/* upper left corner of scroll */
341 	rg.x.dx = (desk_rows << 8) | desk_cols;
342 				/* lower right corner of scroll */
343 #if	COLOR
344 	if (dtype != CDMONO)
345 		if (revflag)
346 			attr = ((ctrans[gfcolor] & 15) << 4) | (ctrans[deskcolor] & 15);
347 		else
348 			attr = ((ctrans[deskcolor] & 15) << 4) | (ctrans[gfcolor] & 15);
349 	else
350 		if (revflag)
351 			attr = 70;
352 		else
353 			attr = 07;
354 #else
355 	attr = 07;
356 #endif
357 
358 	rg.h.bh = attr;
359 	int86(0x10, &rg, &rg);
360 }
361 
ibmrev(state)362 int PASCAL NEAR ibmrev(state)	/* change reverse video state */
363 
364 int state;	/* TRUE = reverse, FALSE = normal */
365 
366 {
367 	revflag = state;
368 }
369 
370 extern dumpscreens();
371 
ibmcres(res)372 int PASCAL NEAR ibmcres(res) /* change screen resolution */
373 
374 char *res;	/* resolution to change to */
375 
376 {
377 	int i;		/* index */
378 
379 	for (i = 0; i < NDRIVE; i++)
380 		if (strcmp(res, scr_drive[i].drv_name) == 0) {
381 			scinit(i);
382 			return(TRUE);
383 		}
384 	return(FALSE);
385 }
386 
spal(mode)387 int PASCAL NEAR spal(mode)	/* reset the pallette registers */
388 
389 char *mode;
390 
391 {
392 	/* nothin here now..... */
393 }
394 
ibmbeep()395 int PASCAL NEAR ibmbeep()
396 {
397 #if	MWC
398 	ttputc(BEL);
399 #else /* MWC */
400 #if	IC
401 	bdos(6, BEL);
402 #else /* IC */
403 	bdos(6, BEL, 0);
404 #endif /* IC */
405 #endif /* MWC */
406 }
407 
ibmopen()408 int PASCAL NEAR ibmopen()
409 {
410 	scinit(CDSENSE);
411 	revexist = TRUE;
412 	revflag = FALSE;
413         ttopen();
414 }
415 
ibmclose()416 int PASCAL NEAR ibmclose()
417 
418 {
419 #if	COLOR
420 	ibmfcol(7);
421 	ibmbcol(0);
422 #endif
423 
424 	/* exit in the same mode that we entered */
425 	if (dtype != orig_mode) {
426 		scinit(orig_mode);
427 		movecursor(term.t_nrow, 0);
428 		TTflush();
429 	}
430 	dtype = -1;
431 	ttclose();
432 }
433 
ibmkopen()434 int PASCAL NEAR ibmkopen()	/* open the keyboard */
435 
436 {
437 	/* find the current state of the control break inturrupt */
438 	rg.h.ah = 0x33;	/* ctrl-break check */
439 	rg.h.al = 0;	/* request the state of the ctrl-break check */
440 	intdos(&rg, &rg);
441 	break_flag = rg.h.dl;
442 
443 	/* set the break processing off if it is on */
444 	if (break_flag == 1) {
445 		rg.h.ah = 0x33;	/* ctrl-break check */
446 		rg.h.al = 1;	/* set the state of the ctrl-break check */
447 		rg.h.dl = 0;	/* turn it off */
448 		intdos(&rg, &rg);
449 	}
450 }
451 
ibmkclose()452 int PASCAL NEAR ibmkclose() /* close the keyboard */
453 
454 {
455 	if (break_flag == 1) {
456 		rg.h.ah = 0x33;	/* ctrl-break check */
457 		rg.h.al = 1;	/* set the state of the ctrl-break check */
458 		rg.h.dl = 1;	/* turn it on */
459 		intdos(&rg, &rg);
460 	}
461 }
462 
scinit(type)463 int PASCAL NEAR scinit(type) /* initialize the screen head pointers */
464 
465 int type;	/* type of adapter to init for */
466 
467 {
468 	/* if asked...find out what display is connected */
469 	if (type == CDSENSE)
470 		type = getboard();
471 
472 	/* if we have nothing to do....don't do it */
473 	if (dtype == type)
474 		return(TRUE);
475 
476 	/* if we try to switch to EGA and there is none, don't */
477 	if (type == CDEGA && !egaexist)
478 		return(FALSE);
479 
480 	/* if we try to switch to VGA and there is none, don't */
481 	if (type == CDVGA && !vgaexist )
482 		return(FALSE);
483 
484 	/* if we had the EGA or VGA open... close it */
485 	if (dtype == CDEGA || dtype == CDVGA || dtype == CDVGA12)
486 		egaclose();
487 
488 	/* if we had the CGA40 open... close it */
489 	if (dtype == CDCGA40)
490 		cga40_close();
491 
492 	/* and set up the various parameters as needed */
493 	scadd = scr_drive[type].drv_scradd;
494 	switch (type) {
495 		case CDMONO:	/* Monochrome adapter */
496 		case CDCGA:	/* Color graphics adapter */
497 				break;
498 
499 		case CDCGA40:	/* Color graphics adapter */
500 				cga40_open();
501 				break;
502 
503 		case CDEGA:	/* Enhanced graphics adapter */
504 				egaopen(CDEGA);
505 				break;
506 
507 		case CDVGA:	/* video graphics array - acts as EGA but more lines */
508 				egaopen(CDVGA);
509 				break;
510 
511 		case CDVGA12:	/* Video Graphics Array 12 line mode */
512 				egaopen(CDVGA12);
513 				break;
514 
515 	}
516 	maxlines(scr_drive[type].drv_rows);
517 
518 	/* reset the $sres environment variable */
519 	strcpy(sres, scr_drive[type].drv_name);
520 
521 	/* resize any screens that need it! */
522 	screen_init(dtype, type);
523 	dtype = type;
524 
525 	return(TRUE);
526 }
527 
screen_init(dtype,type)528 int PASCAL NEAR screen_init(dtype, type) /* initialize the screen head pointers */
529 
530 int dtype;	/* original screen type (-1 if first time!) */
531 int type;	/* new type of adapter to adjust screens for */
532 
533 {
534 	int full_screen;	/* is the active screen full size */
535 
536 	/* is the front screen full size? */
537 	if ((dtype != -1) &&
538 	   (scr_drive[dtype].drv_rows == (term.t_nrow + 1)) &&
539 	    (scr_drive[dtype].drv_cols == term.t_ncol))
540 		full_screen = TRUE;
541 	else
542 		full_screen = FALSE;
543 
544 	/* set up the new desktop size */
545 	desk_rows = scr_drive[type].drv_rows;
546 	desk_cols = scr_drive[type].drv_cols;
547 
548 	/* recalculate the screen line pointer array */
549 	change_width(desk_cols);
550 
551 	/* first time, or if we are full screen */
552 	if ((dtype == -1) || full_screen) {
553 		newsize(TRUE, desk_rows);
554 		newwidth(TRUE, desk_cols);
555 	}
556 
557 #if	WINDOW_TEXT
558 	refresh_screen(first_screen);
559 #endif
560 	return(TRUE);
561 }
562 
change_width(ncols)563 int PASCAL NEAR change_width(ncols)
564 
565 int ncols;	/* number of columns across */
566 
567 {
568 	union {
569 		long laddr;	/* long form of address */
570 		int *paddr;	/* pointer form of address */
571 	} addr;
572 	int i;
573 
574 	/* re-initialize the screen pointer array */
575 	for (i = 0; i < NROW; i++) {
576 		addr.laddr = scadd + (long)(ncols * i * 2);
577 		scptr[i] = addr.paddr;
578 	}
579 }
580 
581 /* getboard:	Determine which type of display board is attached.
582 		Current known types include:
583 
584 		CDMONO	Monochrome graphics adapter
585 		CDCGA	Color Graphics Adapter
586 		CDEGA	Extended graphics Adapter
587 		CDVGA	Vidio Graphics Array
588 
589 		if MONO	set to MONO
590 		   CGA40 set to CGA40	test as appropriate
591 		   CGA	set to CGA	EGAexist = FALSE VGAexist = FALSE
592 		   EGA	set to CGA	EGAexist = TRUE  VGAexist = FALSE
593 		   VGA	set to CGA	EGAexist = TRUE  VGAexist = TRUE
594 */
595 
getboard()596 int PASCAL NEAR getboard()
597 
598 {
599 	int type;	/* board type to return */
600 
601 	type = CDCGA;
602 	int86(0x11, &rg, &rg);
603 	if ((((rg.x.ax >> 4) & 3) == 3))
604 		type = CDMONO;
605 
606 	/* test for 40 col mode */
607 	rg.h.ah = 15;
608 	int86(0x10, &rg, &rg);
609 	if (rg.h.al == 1)
610 		type = CDCGA40;
611 
612 	rg.x.ax = 0x1130;
613 	int86(0x10, &rg, &rg);
614 
615 	if (rg.h.dl == 42)
616 		type = CDEGA;
617 
618 	if (rg.h.dl == 49)
619 		type = CDVGA;
620 
621 	/* save the original video mode */
622 	orig_mode = type;
623 
624 	/* test if EGA present */
625 	rg.x.ax = 0x1200;
626 	rg.x.bx = 0xff10;
627 	int86(0x10,&rg, &rg);		/* If EGA, bh=0-1 and bl=0-3 */
628 	egaexist = !(rg.x.bx & 0xfefc);	/* Yes, it's EGA */
629 	if (egaexist) {
630 		/* Adapter says it's an EGA. We'll get the same response
631 		   from a VGA, so try to tell the two apart */
632 		rg.x.ax = 0x1a00;	/* read display combination */
633 		int86(0x10,&rg,&rg);
634 		if (rg.h.al == 0x1a && (rg.h.bl == 7 || rg.h.bl == 8)) {
635 			/* Function is supported and it's a PS/2 50,60,80 with
636 			   analog display, so it's VGA (I hope!) */
637 			vgaexist = TRUE;
638 		} else {
639 			/* Either BIOS function not supported or something
640 			   other then VGA so set it to be EGA */
641 			vgaexist = FALSE;
642 		}
643 	}
644 	return(type);
645 }
646 
egaopen(mode)647 int PASCAL NEAR egaopen(mode) /* init the computer to work with the EGA or VGA */
648 
649 int mode;	/* mode to select [CDEGA/CDVGA] */
650 
651 {
652 	/* set the proper number of scan lines */
653 	rg.h.ah = 18;
654 	switch (mode) {
655 
656 		case CDEGA:	rg.h.al = 1;
657 				break;
658 
659 		case CDVGA:	rg.h.al = 2;
660 				break;
661 
662 		case CDVGA12:	rg.h.al = 0;
663 				break;
664 
665 	}
666 	rg.h.bl = 48;
667 	int86(16, &rg, &rg);
668 
669 	/* put the beast into EGA 43/VGA 50/VGA 12 line mode */
670 	rg.x.ax = 3;
671 	int86(16, &rg, &rg);
672 
673 	/* set the proper character set */
674 	if (mode == CDVGA12) {
675 		rg.h.al = 20;	/*  to 8 by 16 double dot ROM         */
676 	} else {
677 		rg.h.al = 18;	/*  to 8 by 8 double dot ROM         */
678 	}
679 	rg.h.ah = 17;		/* set char. generator function code */
680 	rg.h.bl = 0;		/* block 0                           */
681 	int86(16, &rg, &rg);
682 
683 	/* select the alternative Print Screen function */
684 	rg.h.ah = 18;		/* alternate select function code    */
685 	rg.h.al = 0;		/* clear AL for no good reason       */
686 	rg.h.bl = 32;		/* alt. print screen routine         */
687 	int86(16, &rg, &rg);
688 
689 	/* resize the cursor */
690 	rg.h.ah = 1;		/* set cursor size function code */
691 	rg.x.cx = 0x0607;	/* turn cursor on code */
692 	int86(0x10, &rg, &rg);
693 
694 	/* video bios bug patch */
695 	outp(0x3d4, 10);
696 	outp(0x3d5, 6);
697 }
698 
egaclose()699 int PASCAL NEAR egaclose()
700 
701 {
702 	/* set the proper number of scan lines for CGA */
703 	rg.h.ah = 18;
704 	rg.h.al = 2;
705 	rg.h.bl = 48;
706 	int86(16, &rg, &rg);
707 
708 	/* put the beast into 80 column mode */
709 	rg.x.ax = 3;
710 	int86(16, &rg, &rg);
711 }
712 
cga40_open()713 int PASCAL NEAR cga40_open()
714 
715 {
716 	/* put the beast into 40 column mode */
717 	rg.x.ax = 1;
718 	int86(16, &rg, &rg);
719 }
720 
cga40_close()721 int PASCAL NEAR cga40_close()
722 
723 {
724 	/* put the beast into 80 column mode */
725 	rg.x.ax = 3;
726 	int86(16, &rg, &rg);
727 }
728 
729 /* scwrite: write a line out to the physical screen */
730 
scwrite(row,outstr,forg,bacg,revleft,revright)731 int PASCAL NEAR scwrite(row, outstr, forg, bacg, revleft, revright)
732 
733 int row;	/* row of screen to place outstr on */
734 char *outstr;	/* string to write out (must be term.t_ncol long) */
735 int forg;	/* forground color of string to write */
736 int bacg;	/* background color */
737 int revleft;	/* first character of reverse video area */
738 int revright;	/* first character of non-reverse video area */
739 
740 {
741 	unsigned int norm_attrib;	/* normal attribute byte mask */
742 	unsigned int rev_attrib;	/* reversed attribute byte mask */
743 	unsigned int *lnptr;	/* pointer to the destination line */
744 	int i;
745 
746 	/* build the attribute bytes */
747 #if	COLOR
748 	if (dtype != CDMONO) {
749 		norm_attrib = ((ctrans[bacg]&7) << 12) | (ctrans[forg] << 8);
750 		rev_attrib = ((ctrans[forg]&7) << 12) | (ctrans[bacg] << 8);
751 	} else {
752 		norm_attrib = 0x0700;
753 		rev_attrib = 0x7000;
754 	}
755 #else
756 	norm_attrib = (((bacg & 15) << 4) | (forg & 15)) << 8;
757 	rev_attrib = (((forg & 15) << 4) | (bacg & 15)) << 8;
758 #endif
759 
760 	/* init the pointer to screen line image */
761 	lnptr = &sline[0];
762 
763 	/* step throught the line, setting the character and attributes */
764 	for (i=0; i<term.t_ncol; i++) {
765 		if (i < revleft || i >= revright)
766 			*lnptr++ = (outstr[i] & 255) | norm_attrib;
767 		else
768 			*lnptr++ = (outstr[i] & 255) | rev_attrib;
769 	}
770 
771 	if (flickcode && (dtype == CDCGA)) {
772 		/* wait for vertical retrace to be off */
773 		while ((inp(0x3da) & 8))
774 			;
775 
776 		/* and to be back on */
777 		while ((inp(0x3da) & 8) == 0)
778 			;
779 	}
780 
781 	/* and send the string out */
782 	movmem(&sline[0], scptr[row+term.t_roworg]+term.t_colorg,term.t_ncol*2);
783 }
784 
785 #if	FLABEL
fnclabel(f,n)786 int PASCAL NEAR fnclabel(f, n)	/* label a function key */
787 
788 int f,n;	/* default flag, numeric argument [unused] */
789 
790 {
791 	/* on machines with no function keys...don't bother */
792 	return(TRUE);
793 }
794 #endif
795 #else
ibmhello()796 ibmhello()
797 {
798 }
799 #endif
800 
801