drivers/wifi: Remove unnecessary data structure copy
[coreboot2.git] / payloads / libpayload / curses / PDCurses / dos / pdcscrn.c
blobfc3bbfc6cbfdf8b9327ea24c51e912c3db62729d
1 /* Public Domain Curses */
3 #include "pdcdos.h"
5 RCSID("$Id: pdcscrn.c,v 1.89 2008/07/13 16:08:17 wmcbrine Exp $")
7 #include <stdlib.h>
9 #ifdef CHTYPE_LONG
10 # define PDC_OFFSET 32
11 #else
12 # define PDC_OFFSET 8
13 #endif
15 /* COLOR_PAIR to attribute encoding table. */
17 unsigned char *pdc_atrtab = (unsigned char *)NULL;
19 int pdc_adapter; /* screen type */
20 int pdc_scrnmode; /* default screen mode */
21 int pdc_font; /* default font size */
22 bool pdc_direct_video; /* allow direct screen memory writes */
23 bool pdc_bogus_adapter; /* TRUE if adapter has insane values */
24 unsigned pdc_video_seg; /* video base segment */
25 unsigned pdc_video_ofs; /* video base offset */
27 static short curstoreal[16], realtocurs[16] =
29 COLOR_BLACK, COLOR_BLUE, COLOR_GREEN, COLOR_CYAN, COLOR_RED,
30 COLOR_MAGENTA, COLOR_YELLOW, COLOR_WHITE, COLOR_BLACK + 8,
31 COLOR_BLUE + 8, COLOR_GREEN + 8, COLOR_CYAN + 8, COLOR_RED + 8,
32 COLOR_MAGENTA + 8, COLOR_YELLOW + 8, COLOR_WHITE + 8
35 static bool sizeable = FALSE; /* TRUE if adapter is resizeable */
37 static unsigned short *saved_screen = NULL;
38 static int saved_lines = 0;
39 static int saved_cols = 0;
41 static int saved_scrnmode[3];
42 static int saved_font[3];
44 /* Thanks to Jeff Duntemann, K16RA for providing the impetus
45 (through the Dr. Dobbs Journal, March 1989 issue) for getting
46 the routines below merged into Bjorn Larsson's PDCurses 1.3...
47 -- frotz@dri.com 900730 */
49 /* _get_font() - Get the current font size */
51 static int _get_font(void)
53 int retval;
55 retval = getdosmemword(0x485);
57 /* Assume the MDS Genius is in 66 line mode. */
59 if ((retval == 0) && (pdc_adapter == _MDS_GENIUS))
60 retval = _FONT15;
62 switch (pdc_adapter)
64 case _MDA:
65 retval = 10; /* POINTS is not certain on MDA/Hercules */
66 break;
68 case _EGACOLOR:
69 case _EGAMONO:
70 switch (retval)
72 case _FONT8:
73 case _FONT14:
74 break;
75 default:
76 retval = _FONT14;
78 break;
80 case _CGA:
81 retval = _FONT8;
84 return retval;
87 /* _set_font() - Sets the current font size, if the adapter allows such a
88 change. It is an error to attempt to change the font size on a
89 "bogus" adapter. The reason for this is that we have a known video
90 adapter identity problem. e.g. Two adapters report the same identifying
91 characteristics. */
93 static void _set_font(int size)
95 PDCREGS regs;
97 if (pdc_bogus_adapter)
98 return;
100 switch (pdc_adapter)
102 case _CGA:
103 case _MDA:
104 case _MCGACOLOR:
105 case _MCGAMONO:
106 case _MDS_GENIUS:
107 break;
109 case _EGACOLOR:
110 case _EGAMONO:
111 if (sizeable && (pdc_font != size))
113 switch (size)
115 case _FONT8:
116 regs.W.ax = 0x1112;
117 regs.h.bl = 0x00;
118 PDCINT(0x10, regs);
119 break;
120 case _FONT14:
121 regs.W.ax = 0x1111;
122 regs.h.bl = 0x00;
123 PDCINT(0x10, regs);
126 break;
128 case _VGACOLOR:
129 case _VGAMONO:
130 if (sizeable && (pdc_font != size))
132 switch (size)
134 case _FONT8:
135 regs.W.ax = 0x1112;
136 regs.h.bl = 0x00;
137 PDCINT(0x10, regs);
138 break;
139 case _FONT14:
140 regs.W.ax = 0x1111;
141 regs.h.bl = 0x00;
142 PDCINT(0x10, regs);
143 break;
144 case _FONT16:
145 regs.W.ax = 0x1114;
146 regs.h.bl = 0x00;
147 PDCINT(0x10, regs);
152 curs_set(SP->visibility);
154 pdc_font = _get_font();
157 /* _set_80x25() - force a known screen state: 80x25 text mode. Forces the
158 appropriate 80x25 alpha mode given the display adapter. */
160 static void _set_80x25(void)
162 PDCREGS regs;
164 switch (pdc_adapter)
166 case _CGA:
167 case _EGACOLOR:
168 case _EGAMONO:
169 case _VGACOLOR:
170 case _VGAMONO:
171 case _MCGACOLOR:
172 case _MCGAMONO:
173 regs.h.ah = 0x00;
174 regs.h.al = 0x03;
175 PDCINT(0x10, regs);
176 break;
177 case _MDA:
178 regs.h.ah = 0x00;
179 regs.h.al = 0x07;
180 PDCINT(0x10, regs);
184 /* _get_scrn_mode() - Return the current BIOS video mode */
186 static int _get_scrn_mode(void)
188 PDCREGS regs;
190 regs.h.ah = 0x0f;
191 PDCINT(0x10, regs);
193 return (int)regs.h.al;
196 /* _set_scrn_mode() - Sets the BIOS Video Mode Number only if it is
197 different from the current video mode. */
199 static void _set_scrn_mode(int new_mode)
201 PDCREGS regs;
203 if (_get_scrn_mode() != new_mode)
205 regs.h.ah = 0;
206 regs.h.al = (unsigned char) new_mode;
207 PDCINT(0x10, regs);
210 pdc_font = _get_font();
211 pdc_scrnmode = new_mode;
212 LINES = PDC_get_rows();
213 COLS = PDC_get_columns();
216 /* _sanity_check() - A video adapter identification sanity check. This
217 routine will force sane values for various control flags. */
219 static int _sanity_check(int adapter)
221 int fontsize = _get_font();
222 int rows = PDC_get_rows();
224 PDC_LOG(("_sanity_check() - called: Adapter %d\n", adapter));
226 switch (adapter)
228 case _EGACOLOR:
229 case _EGAMONO:
230 switch (rows)
232 case 25:
233 case 43:
234 break;
235 default:
236 pdc_bogus_adapter = TRUE;
239 switch (fontsize)
241 case _FONT8:
242 case _FONT14:
243 break;
244 default:
245 pdc_bogus_adapter = TRUE;
247 break;
249 case _VGACOLOR:
250 case _VGAMONO:
251 break;
253 case _CGA:
254 case _MDA:
255 case _MCGACOLOR:
256 case _MCGAMONO:
257 switch (rows)
259 case 25:
260 break;
261 default:
262 pdc_bogus_adapter = TRUE;
264 break;
266 default:
267 pdc_bogus_adapter = TRUE;
270 if (pdc_bogus_adapter)
272 sizeable = FALSE;
273 pdc_direct_video = FALSE;
276 return adapter;
279 /* _query_adapter_type() - Determine PC video adapter type. */
281 static int _query_adapter_type(void)
283 PDCREGS regs;
284 int retval = _NONE;
286 /* thanks to paganini@ax.apc.org for the GO32 fix */
288 #if !defined(__DJGPP__) && !defined(__WATCOMC__)
289 struct SREGS segs;
290 #endif
291 short video_base = getdosmemword(0x463);
293 PDC_LOG(("_query_adapter_type() - called\n"));
295 /* attempt to call VGA Identify Adapter Function */
297 regs.W.ax = 0x1a00;
298 PDCINT(0x10, regs);
300 if ((regs.h.al == 0x1a) && (retval == _NONE))
302 /* We know that the PS/2 video BIOS is alive and well. */
304 switch (regs.h.al)
306 case 0:
307 retval = _NONE;
308 break;
309 case 1:
310 retval = _MDA;
311 break;
312 case 2:
313 retval = _CGA;
314 break;
315 case 4:
316 retval = _EGACOLOR;
317 sizeable = TRUE;
318 break;
319 case 5:
320 retval = _EGAMONO;
321 break;
322 case 26: /* ...alt. VGA BIOS... */
323 case 7:
324 retval = _VGACOLOR;
325 sizeable = TRUE;
326 break;
327 case 8:
328 retval = _VGAMONO;
329 break;
330 case 10:
331 case 13:
332 retval = _MCGACOLOR;
333 break;
334 case 12:
335 retval = _MCGAMONO;
336 break;
337 default:
338 retval = _CGA;
341 else
343 /* No VGA BIOS, check for an EGA BIOS by selecting an
344 Alternate Function Service...
346 bx == 0x0010 --> return EGA information */
348 regs.h.ah = 0x12;
349 regs.W.bx = 0x10;
350 PDCINT(0x10, regs);
352 if ((regs.h.bl != 0x10) && (retval == _NONE))
354 /* An EGA BIOS exists */
356 regs.h.ah = 0x12;
357 regs.h.bl = 0x10;
358 PDCINT(0x10, regs);
360 if (regs.h.bh == 0)
361 retval = _EGACOLOR;
362 else
363 retval = _EGAMONO;
365 else if (retval == _NONE)
367 /* Now we know we only have CGA or MDA */
369 PDCINT(0x11, regs);
371 switch (regs.h.al & 0x30)
373 case 0x10:
374 case 0x20:
375 retval = _CGA;
376 break;
377 case 0x30:
378 retval = _MDA;
379 break;
380 default:
381 retval = _NONE;
386 if (video_base == 0x3d4)
388 pdc_video_seg = 0xb800;
389 switch (retval)
391 case _EGAMONO:
392 retval = _EGACOLOR;
393 break;
394 case _VGAMONO:
395 retval = _VGACOLOR;
399 if (video_base == 0x3b4)
401 pdc_video_seg = 0xb000;
402 switch (retval)
404 case _EGACOLOR:
405 retval = _EGAMONO;
406 break;
407 case _VGACOLOR:
408 retval = _VGAMONO;
412 if ((retval == _NONE)
413 #ifndef CGA_DIRECT
414 || (retval == _CGA)
415 #endif
417 pdc_direct_video = FALSE;
419 if ((unsigned)pdc_video_seg == 0xb000)
420 SP->mono = TRUE;
421 else
422 SP->mono = FALSE;
424 /* Check for DESQview shadow buffer
425 thanks to paganini@ax.apc.org for the GO32 fix */
427 #ifndef __WATCOMC__
428 regs.h.ah = 0xfe;
429 regs.h.al = 0;
430 regs.x.di = pdc_video_ofs;
431 # ifdef __DJGPP__
432 regs.x.es = pdc_video_seg;
433 __dpmi_int(0x10, &regs);
434 pdc_video_seg = regs.x.es;
435 # else
436 segs.es = pdc_video_seg;
437 int86x(0x10, &regs, &regs, &segs);
438 pdc_video_seg = segs.es;
439 # endif
440 pdc_video_ofs = regs.x.di;
441 #endif
442 if (!pdc_adapter)
443 pdc_adapter = retval;
445 return _sanity_check(retval);
448 /* close the physical screen -- may restore the screen to its state
449 before PDC_scr_open(); miscellaneous cleanup */
451 void PDC_scr_close(void)
453 #if SMALL || MEDIUM
454 # ifndef __PACIFIC__
455 struct SREGS segregs;
456 # endif
457 int ds;
458 #endif
459 PDC_LOG(("PDC_scr_close() - called\n"));
461 if (getenv("PDC_RESTORE_SCREEN") && saved_screen)
463 #ifdef __DJGPP__
464 dosmemput(saved_screen, saved_lines * saved_cols * 2,
465 (unsigned long)_FAR_POINTER(pdc_video_seg,
466 pdc_video_ofs));
467 #else
468 # if (SMALL || MEDIUM)
469 # ifdef __PACIFIC__
470 ds = FP_SEG((void far *)saved_screen);
471 # else
472 segread(&segregs);
473 ds = segregs.ds;
474 # endif
475 movedata(ds, (int)saved_screen, pdc_video_seg, pdc_video_ofs,
476 (saved_lines * saved_cols * 2));
477 # else
478 memcpy((void *)_FAR_POINTER(pdc_video_seg, pdc_video_ofs),
479 (void *)saved_screen, (saved_lines * saved_cols * 2));
480 # endif
481 #endif
482 free(saved_screen);
483 saved_screen = NULL;
486 reset_shell_mode();
488 if (SP->visibility != 1)
489 curs_set(1);
491 /* Position cursor to the bottom left of the screen. */
493 PDC_gotoyx(PDC_get_rows() - 2, 0);
496 void PDC_scr_free(void)
498 if (SP)
499 free(SP);
500 if (pdc_atrtab)
501 free(pdc_atrtab);
503 pdc_atrtab = (unsigned char *)NULL;
506 /* open the physical screen -- allocate SP, miscellaneous intialization,
507 and may save the existing screen for later restoration */
509 int PDC_scr_open(int argc, char **argv)
511 #if SMALL || MEDIUM
512 # ifndef __PACIFIC__
513 struct SREGS segregs;
514 # endif
515 int ds;
516 #endif
517 int i;
519 PDC_LOG(("PDC_scr_open() - called\n"));
521 SP = calloc(1, sizeof(SCREEN));
522 pdc_atrtab = calloc(PDC_COLOR_PAIRS * PDC_OFFSET, 1);
524 if (!SP || !pdc_atrtab)
525 return ERR;
527 for (i = 0; i < 16; i++)
528 curstoreal[realtocurs[i]] = i;
530 SP->orig_attr = FALSE;
532 pdc_direct_video = TRUE; /* Assume that we can */
533 pdc_video_seg = 0xb000; /* Base screen segment addr */
534 pdc_video_ofs = 0x0; /* Base screen segment ofs */
536 pdc_adapter = _query_adapter_type();
537 pdc_scrnmode = _get_scrn_mode();
538 pdc_font = _get_font();
540 SP->lines = PDC_get_rows();
541 SP->cols = PDC_get_columns();
543 SP->mouse_wait = PDC_CLICK_PERIOD;
544 SP->audible = TRUE;
546 /* If the environment variable PDCURSES_BIOS is set, the DOS int10()
547 BIOS calls are used in place of direct video memory access. */
549 if (getenv("PDCURSES_BIOS"))
550 pdc_direct_video = FALSE;
552 /* This code for preserving the current screen. */
554 if (getenv("PDC_RESTORE_SCREEN"))
556 saved_lines = SP->lines;
557 saved_cols = SP->cols;
559 saved_screen = malloc(saved_lines * saved_cols * 2);
561 if (!saved_screen)
563 SP->_preserve = FALSE;
564 return OK;
566 #ifdef __DJGPP__
567 dosmemget((unsigned long)_FAR_POINTER(pdc_video_seg, pdc_video_ofs),
568 saved_lines * saved_cols * 2, saved_screen);
569 #else
570 # if SMALL || MEDIUM
571 # ifdef __PACIFIC__
572 ds = FP_SEG((void far *) saved_screen);
573 # else
574 segread(&segregs);
575 ds = segregs.ds;
576 # endif
577 movedata(pdc_video_seg, pdc_video_ofs, ds, (int)saved_screen,
578 (saved_lines * saved_cols * 2));
579 # else
580 memcpy((void *)saved_screen,
581 (void *)_FAR_POINTER(pdc_video_seg, pdc_video_ofs),
582 (saved_lines * saved_cols * 2));
583 # endif
584 #endif
587 SP->_preserve = (getenv("PDC_PRESERVE_SCREEN") != NULL);
589 return OK;
592 /* the core of resize_term() */
594 int PDC_resize_screen(int nlines, int ncols)
596 PDC_LOG(("PDC_resize_screen() - called. Lines: %d Cols: %d\n",
597 nlines, ncols));
599 /* Trash the stored value of orig_cursor -- it's only good if the
600 video mode doesn't change */
602 SP->orig_cursor = 0x0607;
604 switch (pdc_adapter)
606 case _EGACOLOR:
607 if (nlines >= 43)
608 _set_font(_FONT8);
609 else
610 _set_80x25();
611 break;
613 case _VGACOLOR:
614 if (nlines > 28)
615 _set_font(_FONT8);
616 else
617 if (nlines > 25)
618 _set_font(_FONT14);
619 else
620 _set_80x25();
623 PDC_set_blink(COLORS == 8);
625 return OK;
628 void PDC_reset_prog_mode(void)
630 PDC_LOG(("PDC_reset_prog_mode() - called.\n"));
633 void PDC_reset_shell_mode(void)
635 PDC_LOG(("PDC_reset_shell_mode() - called.\n"));
638 void PDC_restore_screen_mode(int i)
640 if (i >= 0 && i <= 2)
642 pdc_font = _get_font();
643 _set_font(saved_font[i]);
645 if (_get_scrn_mode() != saved_scrnmode[i])
646 _set_scrn_mode(saved_scrnmode[i]);
650 void PDC_save_screen_mode(int i)
652 if (i >= 0 && i <= 2)
654 saved_font[i] = pdc_font;
655 saved_scrnmode[i] = pdc_scrnmode;
659 void PDC_init_pair(short pair, short fg, short bg)
661 unsigned char att, temp_bg;
662 chtype i;
664 fg = curstoreal[fg];
665 bg = curstoreal[bg];
667 for (i = 0; i < PDC_OFFSET; i++)
669 att = fg | (bg << 4);
671 if (i & (A_REVERSE >> PDC_ATTR_SHIFT))
672 att = bg | (fg << 4);
673 if (i & (A_UNDERLINE >> PDC_ATTR_SHIFT))
674 att = 1;
675 if (i & (A_INVIS >> PDC_ATTR_SHIFT))
677 temp_bg = att >> 4;
678 att = temp_bg << 4 | temp_bg;
680 if (i & (A_BOLD >> PDC_ATTR_SHIFT))
681 att |= 8;
682 if (i & (A_BLINK >> PDC_ATTR_SHIFT))
683 att |= 128;
685 pdc_atrtab[pair * PDC_OFFSET + i] = att;
689 int PDC_pair_content(short pair, short *fg, short *bg)
691 *fg = realtocurs[pdc_atrtab[pair * PDC_OFFSET] & 0x0F];
692 *bg = realtocurs[(pdc_atrtab[pair * PDC_OFFSET] & 0xF0) >> 4];
694 return OK;
697 /* _egapal() - Find the EGA palette value (0-63) for the color (0-15).
698 On VGA, this is an index into the DAC. */
700 static short _egapal(short color)
702 PDCREGS regs;
704 regs.W.ax = 0x1007;
705 regs.h.bl = curstoreal[color];
707 PDCINT(0x10, regs);
709 return regs.h.bh;
712 bool PDC_can_change_color(void)
714 return (pdc_adapter == _VGACOLOR);
717 /* These are only valid when pdc_adapter == _VGACOLOR */
719 int PDC_color_content(short color, short *red, short *green, short *blue)
721 PDCREGS regs;
723 /* Read single DAC register */
725 regs.W.ax = 0x1015;
726 regs.h.bl = _egapal(color);
728 PDCINT(0x10, regs);
730 /* Scale and store */
732 *red = DIVROUND((unsigned)(regs.h.dh) * 1000, 63);
733 *green = DIVROUND((unsigned)(regs.h.ch) * 1000, 63);
734 *blue = DIVROUND((unsigned)(regs.h.cl) * 1000, 63);
736 return OK;
739 int PDC_init_color(short color, short red, short green, short blue)
741 PDCREGS regs;
743 /* Scale */
745 regs.h.dh = DIVROUND((unsigned)red * 63, 1000);
746 regs.h.ch = DIVROUND((unsigned)green * 63, 1000);
747 regs.h.cl = DIVROUND((unsigned)blue * 63, 1000);
749 /* Set single DAC register */
751 regs.W.ax = 0x1010;
752 regs.W.bx = _egapal(color);
754 PDCINT(0x10, regs);
756 return OK;