diff options
Diffstat (limited to 'payloads/libpayload/curses/PDCurses-3.4/dos/pdcscrn.c')
-rw-r--r-- | payloads/libpayload/curses/PDCurses-3.4/dos/pdcscrn.c | 757 |
1 files changed, 757 insertions, 0 deletions
diff --git a/payloads/libpayload/curses/PDCurses-3.4/dos/pdcscrn.c b/payloads/libpayload/curses/PDCurses-3.4/dos/pdcscrn.c new file mode 100644 index 0000000000..ddfb095677 --- /dev/null +++ b/payloads/libpayload/curses/PDCurses-3.4/dos/pdcscrn.c @@ -0,0 +1,757 @@ +/* Public Domain Curses */ + +#include "pdcdos.h" + +RCSID("$Id: pdcscrn.c,v 1.89 2008/07/13 16:08:17 wmcbrine Exp $") + +#include <stdlib.h> + +#ifdef CHTYPE_LONG +# define PDC_OFFSET 32 +#else +# define PDC_OFFSET 8 +#endif + +/* COLOR_PAIR to attribute encoding table. */ + +unsigned char *pdc_atrtab = (unsigned char *)NULL; + +int pdc_adapter; /* screen type */ +int pdc_scrnmode; /* default screen mode */ +int pdc_font; /* default font size */ +bool pdc_direct_video; /* allow direct screen memory writes */ +bool pdc_bogus_adapter; /* TRUE if adapter has insane values */ +unsigned pdc_video_seg; /* video base segment */ +unsigned pdc_video_ofs; /* video base offset */ + +static short curstoreal[16], realtocurs[16] = +{ + COLOR_BLACK, COLOR_BLUE, COLOR_GREEN, COLOR_CYAN, COLOR_RED, + COLOR_MAGENTA, COLOR_YELLOW, COLOR_WHITE, COLOR_BLACK + 8, + COLOR_BLUE + 8, COLOR_GREEN + 8, COLOR_CYAN + 8, COLOR_RED + 8, + COLOR_MAGENTA + 8, COLOR_YELLOW + 8, COLOR_WHITE + 8 +}; + +static bool sizeable = FALSE; /* TRUE if adapter is resizeable */ + +static unsigned short *saved_screen = NULL; +static int saved_lines = 0; +static int saved_cols = 0; + +static int saved_scrnmode[3]; +static int saved_font[3]; + +/* Thanks to Jeff Duntemann, K16RA for providing the impetus + (through the Dr. Dobbs Journal, March 1989 issue) for getting + the routines below merged into Bjorn Larsson's PDCurses 1.3... + -- frotz@dri.com 900730 */ + +/* _get_font() - Get the current font size */ + +static int _get_font(void) +{ + int retval; + + retval = getdosmemword(0x485); + + /* Assume the MDS Genius is in 66 line mode. */ + + if ((retval == 0) && (pdc_adapter == _MDS_GENIUS)) + retval = _FONT15; + + switch (pdc_adapter) + { + case _MDA: + retval = 10; /* POINTS is not certain on MDA/Hercules */ + break; + + case _EGACOLOR: + case _EGAMONO: + switch (retval) + { + case _FONT8: + case _FONT14: + break; + default: + retval = _FONT14; + } + break; + + case _CGA: + retval = _FONT8; + } + + return retval; +} + +/* _set_font() - Sets the current font size, if the adapter allows such a + change. It is an error to attempt to change the font size on a + "bogus" adapter. The reason for this is that we have a known video + adapter identity problem. e.g. Two adapters report the same identifying + characteristics. */ + +static void _set_font(int size) +{ + PDCREGS regs; + + if (pdc_bogus_adapter) + return; + + switch (pdc_adapter) + { + case _CGA: + case _MDA: + case _MCGACOLOR: + case _MCGAMONO: + case _MDS_GENIUS: + break; + + case _EGACOLOR: + case _EGAMONO: + if (sizeable && (pdc_font != size)) + { + switch (size) + { + case _FONT8: + regs.W.ax = 0x1112; + regs.h.bl = 0x00; + PDCINT(0x10, regs); + break; + case _FONT14: + regs.W.ax = 0x1111; + regs.h.bl = 0x00; + PDCINT(0x10, regs); + } + } + break; + + case _VGACOLOR: + case _VGAMONO: + if (sizeable && (pdc_font != size)) + { + switch (size) + { + case _FONT8: + regs.W.ax = 0x1112; + regs.h.bl = 0x00; + PDCINT(0x10, regs); + break; + case _FONT14: + regs.W.ax = 0x1111; + regs.h.bl = 0x00; + PDCINT(0x10, regs); + break; + case _FONT16: + regs.W.ax = 0x1114; + regs.h.bl = 0x00; + PDCINT(0x10, regs); + } + } + } + + curs_set(SP->visibility); + + pdc_font = _get_font(); +} + +/* _set_80x25() - force a known screen state: 80x25 text mode. Forces the + appropriate 80x25 alpha mode given the display adapter. */ + +static void _set_80x25(void) +{ + PDCREGS regs; + + switch (pdc_adapter) + { + case _CGA: + case _EGACOLOR: + case _EGAMONO: + case _VGACOLOR: + case _VGAMONO: + case _MCGACOLOR: + case _MCGAMONO: + regs.h.ah = 0x00; + regs.h.al = 0x03; + PDCINT(0x10, regs); + break; + case _MDA: + regs.h.ah = 0x00; + regs.h.al = 0x07; + PDCINT(0x10, regs); + } +} + +/* _get_scrn_mode() - Return the current BIOS video mode */ + +static int _get_scrn_mode(void) +{ + PDCREGS regs; + + regs.h.ah = 0x0f; + PDCINT(0x10, regs); + + return (int)regs.h.al; +} + +/* _set_scrn_mode() - Sets the BIOS Video Mode Number only if it is + different from the current video mode. */ + +static void _set_scrn_mode(int new_mode) +{ + PDCREGS regs; + + if (_get_scrn_mode() != new_mode) + { + regs.h.ah = 0; + regs.h.al = (unsigned char) new_mode; + PDCINT(0x10, regs); + } + + pdc_font = _get_font(); + pdc_scrnmode = new_mode; + LINES = PDC_get_rows(); + COLS = PDC_get_columns(); +} + +/* _sanity_check() - A video adapter identification sanity check. This + routine will force sane values for various control flags. */ + +static int _sanity_check(int adapter) +{ + int fontsize = _get_font(); + int rows = PDC_get_rows(); + + PDC_LOG(("_sanity_check() - called: Adapter %d\n", adapter)); + + switch (adapter) + { + case _EGACOLOR: + case _EGAMONO: + switch (rows) + { + case 25: + case 43: + break; + default: + pdc_bogus_adapter = TRUE; + } + + switch (fontsize) + { + case _FONT8: + case _FONT14: + break; + default: + pdc_bogus_adapter = TRUE; + } + break; + + case _VGACOLOR: + case _VGAMONO: + break; + + case _CGA: + case _MDA: + case _MCGACOLOR: + case _MCGAMONO: + switch (rows) + { + case 25: + break; + default: + pdc_bogus_adapter = TRUE; + } + break; + + default: + pdc_bogus_adapter = TRUE; + } + + if (pdc_bogus_adapter) + { + sizeable = FALSE; + pdc_direct_video = FALSE; + } + + return adapter; +} + +/* _query_adapter_type() - Determine PC video adapter type. */ + +static int _query_adapter_type(void) +{ + PDCREGS regs; + int retval = _NONE; + + /* thanks to paganini@ax.apc.org for the GO32 fix */ + +#if !defined(__DJGPP__) && !defined(__WATCOMC__) + struct SREGS segs; +#endif + short video_base = getdosmemword(0x463); + + PDC_LOG(("_query_adapter_type() - called\n")); + + /* attempt to call VGA Identify Adapter Function */ + + regs.W.ax = 0x1a00; + PDCINT(0x10, regs); + + if ((regs.h.al == 0x1a) && (retval == _NONE)) + { + /* We know that the PS/2 video BIOS is alive and well. */ + + switch (regs.h.al) + { + case 0: + retval = _NONE; + break; + case 1: + retval = _MDA; + break; + case 2: + retval = _CGA; + break; + case 4: + retval = _EGACOLOR; + sizeable = TRUE; + break; + case 5: + retval = _EGAMONO; + break; + case 26: /* ...alt. VGA BIOS... */ + case 7: + retval = _VGACOLOR; + sizeable = TRUE; + break; + case 8: + retval = _VGAMONO; + break; + case 10: + case 13: + retval = _MCGACOLOR; + break; + case 12: + retval = _MCGAMONO; + break; + default: + retval = _CGA; + } + } + else + { + /* No VGA BIOS, check for an EGA BIOS by selecting an + Alternate Function Service... + + bx == 0x0010 --> return EGA information */ + + regs.h.ah = 0x12; + regs.W.bx = 0x10; + PDCINT(0x10, regs); + + if ((regs.h.bl != 0x10) && (retval == _NONE)) + { + /* An EGA BIOS exists */ + + regs.h.ah = 0x12; + regs.h.bl = 0x10; + PDCINT(0x10, regs); + + if (regs.h.bh == 0) + retval = _EGACOLOR; + else + retval = _EGAMONO; + } + else if (retval == _NONE) + { + /* Now we know we only have CGA or MDA */ + + PDCINT(0x11, regs); + + switch (regs.h.al & 0x30) + { + case 0x10: + case 0x20: + retval = _CGA; + break; + case 0x30: + retval = _MDA; + break; + default: + retval = _NONE; + } + } + } + + if (video_base == 0x3d4) + { + pdc_video_seg = 0xb800; + switch (retval) + { + case _EGAMONO: + retval = _EGACOLOR; + break; + case _VGAMONO: + retval = _VGACOLOR; + } + } + + if (video_base == 0x3b4) + { + pdc_video_seg = 0xb000; + switch (retval) + { + case _EGACOLOR: + retval = _EGAMONO; + break; + case _VGACOLOR: + retval = _VGAMONO; + } + } + + if ((retval == _NONE) +#ifndef CGA_DIRECT + || (retval == _CGA) +#endif + ) + pdc_direct_video = FALSE; + + if ((unsigned)pdc_video_seg == 0xb000) + SP->mono = TRUE; + else + SP->mono = FALSE; + + /* Check for DESQview shadow buffer + thanks to paganini@ax.apc.org for the GO32 fix */ + +#ifndef __WATCOMC__ + regs.h.ah = 0xfe; + regs.h.al = 0; + regs.x.di = pdc_video_ofs; +# ifdef __DJGPP__ + regs.x.es = pdc_video_seg; + __dpmi_int(0x10, ®s); + pdc_video_seg = regs.x.es; +# else + segs.es = pdc_video_seg; + int86x(0x10, ®s, ®s, &segs); + pdc_video_seg = segs.es; +# endif + pdc_video_ofs = regs.x.di; +#endif + if (!pdc_adapter) + pdc_adapter = retval; + + return _sanity_check(retval); +} + +/* close the physical screen -- may restore the screen to its state + before PDC_scr_open(); miscellaneous cleanup */ + +void PDC_scr_close(void) +{ +#if SMALL || MEDIUM +# ifndef __PACIFIC__ + struct SREGS segregs; +# endif + int ds; +#endif + PDC_LOG(("PDC_scr_close() - called\n")); + + if (getenv("PDC_RESTORE_SCREEN") && saved_screen) + { +#ifdef __DJGPP__ + dosmemput(saved_screen, saved_lines * saved_cols * 2, + (unsigned long)_FAR_POINTER(pdc_video_seg, + pdc_video_ofs)); +#else +# if (SMALL || MEDIUM) +# ifdef __PACIFIC__ + ds = FP_SEG((void far *)saved_screen); +# else + segread(&segregs); + ds = segregs.ds; +# endif + movedata(ds, (int)saved_screen, pdc_video_seg, pdc_video_ofs, + (saved_lines * saved_cols * 2)); +# else + memcpy((void *)_FAR_POINTER(pdc_video_seg, pdc_video_ofs), + (void *)saved_screen, (saved_lines * saved_cols * 2)); +# endif +#endif + free(saved_screen); + saved_screen = NULL; + } + + reset_shell_mode(); + + if (SP->visibility != 1) + curs_set(1); + + /* Position cursor to the bottom left of the screen. */ + + PDC_gotoyx(PDC_get_rows() - 2, 0); +} + +void PDC_scr_free(void) +{ + if (SP) + free(SP); + if (pdc_atrtab) + free(pdc_atrtab); + + pdc_atrtab = (unsigned char *)NULL; +} + +/* open the physical screen -- allocate SP, miscellaneous intialization, + and may save the existing screen for later restoration */ + +int PDC_scr_open(int argc, char **argv) +{ +#if SMALL || MEDIUM +# ifndef __PACIFIC__ + struct SREGS segregs; +# endif + int ds; +#endif + int i; + + PDC_LOG(("PDC_scr_open() - called\n")); + + SP = calloc(1, sizeof(SCREEN)); + pdc_atrtab = calloc(PDC_COLOR_PAIRS * PDC_OFFSET, 1); + + if (!SP || !pdc_atrtab) + return ERR; + + for (i = 0; i < 16; i++) + curstoreal[realtocurs[i]] = i; + + SP->orig_attr = FALSE; + + pdc_direct_video = TRUE; /* Assume that we can */ + pdc_video_seg = 0xb000; /* Base screen segment addr */ + pdc_video_ofs = 0x0; /* Base screen segment ofs */ + + pdc_adapter = _query_adapter_type(); + pdc_scrnmode = _get_scrn_mode(); + pdc_font = _get_font(); + + SP->lines = PDC_get_rows(); + SP->cols = PDC_get_columns(); + + SP->mouse_wait = PDC_CLICK_PERIOD; + SP->audible = TRUE; + + /* If the environment variable PDCURSES_BIOS is set, the DOS int10() + BIOS calls are used in place of direct video memory access. */ + + if (getenv("PDCURSES_BIOS")) + pdc_direct_video = FALSE; + + /* This code for preserving the current screen. */ + + if (getenv("PDC_RESTORE_SCREEN")) + { + saved_lines = SP->lines; + saved_cols = SP->cols; + + saved_screen = malloc(saved_lines * saved_cols * 2); + + if (!saved_screen) + { + SP->_preserve = FALSE; + return OK; + } +#ifdef __DJGPP__ + dosmemget((unsigned long)_FAR_POINTER(pdc_video_seg, pdc_video_ofs), + saved_lines * saved_cols * 2, saved_screen); +#else +# if SMALL || MEDIUM +# ifdef __PACIFIC__ + ds = FP_SEG((void far *) saved_screen); +# else + segread(&segregs); + ds = segregs.ds; +# endif + movedata(pdc_video_seg, pdc_video_ofs, ds, (int)saved_screen, + (saved_lines * saved_cols * 2)); +# else + memcpy((void *)saved_screen, + (void *)_FAR_POINTER(pdc_video_seg, pdc_video_ofs), + (saved_lines * saved_cols * 2)); +# endif +#endif + } + + SP->_preserve = (getenv("PDC_PRESERVE_SCREEN") != NULL); + + return OK; +} + +/* the core of resize_term() */ + +int PDC_resize_screen(int nlines, int ncols) +{ + PDC_LOG(("PDC_resize_screen() - called. Lines: %d Cols: %d\n", + nlines, ncols)); + + /* Trash the stored value of orig_cursor -- it's only good if the + video mode doesn't change */ + + SP->orig_cursor = 0x0607; + + switch (pdc_adapter) + { + case _EGACOLOR: + if (nlines >= 43) + _set_font(_FONT8); + else + _set_80x25(); + break; + + case _VGACOLOR: + if (nlines > 28) + _set_font(_FONT8); + else + if (nlines > 25) + _set_font(_FONT14); + else + _set_80x25(); + } + + PDC_set_blink(COLORS == 8); + + return OK; +} + +void PDC_reset_prog_mode(void) +{ + PDC_LOG(("PDC_reset_prog_mode() - called.\n")); +} + +void PDC_reset_shell_mode(void) +{ + PDC_LOG(("PDC_reset_shell_mode() - called.\n")); +} + +void PDC_restore_screen_mode(int i) +{ + if (i >= 0 && i <= 2) + { + pdc_font = _get_font(); + _set_font(saved_font[i]); + + if (_get_scrn_mode() != saved_scrnmode[i]) + _set_scrn_mode(saved_scrnmode[i]); + } +} + +void PDC_save_screen_mode(int i) +{ + if (i >= 0 && i <= 2) + { + saved_font[i] = pdc_font; + saved_scrnmode[i] = pdc_scrnmode; + } +} + +void PDC_init_pair(short pair, short fg, short bg) +{ + unsigned char att, temp_bg; + chtype i; + + fg = curstoreal[fg]; + bg = curstoreal[bg]; + + for (i = 0; i < PDC_OFFSET; i++) + { + att = fg | (bg << 4); + + if (i & (A_REVERSE >> PDC_ATTR_SHIFT)) + att = bg | (fg << 4); + if (i & (A_UNDERLINE >> PDC_ATTR_SHIFT)) + att = 1; + if (i & (A_INVIS >> PDC_ATTR_SHIFT)) + { + temp_bg = att >> 4; + att = temp_bg << 4 | temp_bg; + } + if (i & (A_BOLD >> PDC_ATTR_SHIFT)) + att |= 8; + if (i & (A_BLINK >> PDC_ATTR_SHIFT)) + att |= 128; + + pdc_atrtab[pair * PDC_OFFSET + i] = att; + } +} + +int PDC_pair_content(short pair, short *fg, short *bg) +{ + *fg = realtocurs[pdc_atrtab[pair * PDC_OFFSET] & 0x0F]; + *bg = realtocurs[(pdc_atrtab[pair * PDC_OFFSET] & 0xF0) >> 4]; + + return OK; +} + +/* _egapal() - Find the EGA palette value (0-63) for the color (0-15). + On VGA, this is an index into the DAC. */ + +static short _egapal(short color) +{ + PDCREGS regs; + + regs.W.ax = 0x1007; + regs.h.bl = curstoreal[color]; + + PDCINT(0x10, regs); + + return regs.h.bh; +} + +bool PDC_can_change_color(void) +{ + return (pdc_adapter == _VGACOLOR); +} + +/* These are only valid when pdc_adapter == _VGACOLOR */ + +int PDC_color_content(short color, short *red, short *green, short *blue) +{ + PDCREGS regs; + + /* Read single DAC register */ + + regs.W.ax = 0x1015; + regs.h.bl = _egapal(color); + + PDCINT(0x10, regs); + + /* Scale and store */ + + *red = DIVROUND((unsigned)(regs.h.dh) * 1000, 63); + *green = DIVROUND((unsigned)(regs.h.ch) * 1000, 63); + *blue = DIVROUND((unsigned)(regs.h.cl) * 1000, 63); + + return OK; +} + +int PDC_init_color(short color, short red, short green, short blue) +{ + PDCREGS regs; + + /* Scale */ + + regs.h.dh = DIVROUND((unsigned)red * 63, 1000); + regs.h.ch = DIVROUND((unsigned)green * 63, 1000); + regs.h.cl = DIVROUND((unsigned)blue * 63, 1000); + + /* Set single DAC register */ + + regs.W.ax = 0x1010; + regs.W.bx = _egapal(color); + + PDCINT(0x10, regs); + + return OK; +} |