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