/* _vid_setmode.c *********** Copyright 1988-1992 by Vermont Creative Software *********** vid_setmode() Switches to a new display adapter and/or video mode under PCDOS and OS/2 Call #include void _vid_setmode(vidmode, setflag) int vidmode; Video mode number to switch to int setflag; Change video mode indicator for GraphEx vidmode: Specify the mode number or the symbolic mode value of the mode you are switching to. The mode numbers are the same as those used in the ROM BIOS. The symbolic values are the same as those used in the DOS 2.0+ MODE command. The mode numbers and symbolic values are as follows: setflag: Indicates video mode is changing - required for GraphEx #ifndef GRAPH_EX MODE SYMBOLIC VIDEO NUMBER MODE VALUE MODE DISPLAY 0 BW40 Text Mode 40x25 B&W 1 CO40 Text Mode 40x25 Color 2 BW80 Text Mode 80x25 B&W 3 CO80 Text Mode 80x25 Color 4 -- Graphics Mode 320x200 Color 5 -- Graphics Mode 320x200 B&W 6 -- Graphics Mode 640x200 B&W 7 MONO Monochrome Board >=8 -- Graphics Modes #endif #ifdef GRAPH_EX MODE SYMBOLIC VIDEO NUMBER MODE VALUE MODE DISPLAY (decimal) (hex) 0 BW40 Text Mode 40x25 B&W 1 CO40 Text Mode 40x25 Color 2 BW80 Text Mode 80x25 B&W 3 CO80 Text Mode 80x25 Color 4 -- Graphics Mode 320x200 Color 5 -- Graphics Mode 320x200 B&W 6 CGM Graphics Mode 640x200 B&W 7 MONO Monochrome Board 16 10 EGM Graphics Mode 640x350 16 color 18 12 VGM16 Graphics Mode 640x480 16 color 19 13 VGM256 Graphics Mode 320x200 256 color 88 58 PAR800 Graphics Mode 800x600 16 color 91 5b TRI800 Graphics Mode 800x600 16 color 93 5d TRI256 Graphics Mode 640x480 256 color 272 110 HGM Graphics Mode 720x348 B&W Note: Vermont Views GraphEx is required to use any graphics modes. #endif Returns None Description PCDOS and OS/2 Systems: vid_setmode() sets the video mode on the IBM PC and allows displays to be switched dynamically. If the mode number specified in the call is less than 0, the function returns immediately. Otherwise, the mode number is used to set the proper equipment flag value in the BIOS data area. vid_int() is called to reset the mode. Under PCDOS, vid_int() uses the interrupt INT 10H, function 0. Under OS/2, vid_int() calls VioSetMode(). This action will clear the screen. After the mode is changed, the system is re-initialized (if it had been initialized previously). The current video screen clear attribute is retained. If the previous and new modes are both text and have the same number of rows and columns on the video screen, the current full screen window FULL_WNP, the default window (WN_WNP) and message window (MSG_WNP) templates are also retained. If the new and old video modes are both text and the video screen size changes, WN_WNP and FULL_WNP are re-sized to cover the full screen. MSG_WNP is re-sized to cover the last row of the screen. Any existing saved window images and underlying screen images are retained in the window structures. Also, the user initialization function, if installed, is called during this re-initialization. #ifdef GRAPH_EX PCDOS Systems with GraphEx: If using an unsupported display environment with a custom Vermont Views GraphEx shell structure, the number specified as the mode can in the structure can be passed to _vid_setmode() to switch to that mode. #endif UNIX and VMS Systems: This is a no-op function. Related Functions #ifndef GRAPH_EX vv_init(), vid_getmode() #endif #ifdef GRAPH_EX vv_init(), vid_getmode(), vid_usemode() #endif Cautions vid_setmode() is specific to the PCDOS and OS/2 versions. It returns without doing anything under UNIX and VMS. vid_setmode() is a macro and does no error checking. Macros are not listed by the VCS error reporting system. PCDOS and OS/2 Systems: Vermont Views does not support any graphics modes. If vid_setmode() is called for a mode number from 4-6 or greater than 7, all video display routines of Vermont Views will be inoperative. Use Vermont Views GraphEx to support graphics modes. If the size of the video screen is changed within text modes, the full screen window FULL_WNP is re-sized. Be aware, however, that any stored window image for FULL_WNP remains the same size. If you restore a window image on the screen with wi_unsav() or wi_rpl(), you will get odd results. If vid_setmode() is called after vv_init(), the Vermont Views basic system will be re-initialized and the user initialization function, if any, will be called again. Only the basic system is re-initialized in this case. The help, choice list, and form processing systems are not re-initialized. */ #include #include #ifdef GRAPH_EX #include #endif #ifdef MEMEX #include #endif #define COLOR_MASK 0x20 #define MONO_MASK 0x30 #define COL40_MASK 0x10 #define EQUIP_FLAG (UCHAR FAR *) (_bios_seg + 0x0010) #define DISP_MASK 0xCF #define VI_MODE 0x0000 /*set mode */ #ifdef OLD_STYLE void FASTCALL _vid_setmode(vidmode, setflag) int vidmode; int setflag; #else void FASTCALL _vid_setmode(int vidmode, int setflag) #endif { UCHAR flag_mask; /*mask for right display bits in flag */ VIDIO vr; /*vidio interupt register structure */ #ifdef GRAPH_EX unsigned short i; int savetype; int saverowq; int savecolq; #ifdef LINT_ARGS void (FASTCALL *modeinitfp)(GMODEELE *); #else void (FASTCALL *modeinitfp)(); #endif /* LINT_ARGS */ #endif /* GRAPH_EX */ int new_size = FALSE; /* TRUE if screen size changes */ int tusecount; /* storage for _vid_scr's use count */ UCHAR tclratt; /* storage for the clear attribute */ /* temporary window storage */ WINDOW tfullwn, tvcswn, twn_wn, tmsg_wn; #ifndef NO_DEBUG_CODE static UCHAR fn[] = "vid_setmode"; #endif if (_vv_init) INIT_MODULE(fn); if (vidmode < 0) /*negative mode does not exist */ goto END; if (((_v_mode == BW80 || _v_mode == CO80 || _v_mode == MONO) && (vidmode == BW40 || vidmode == CO40)) || ((vidmode == BW80 || vidmode == CO80 || vidmode == MONO) && (_v_mode == BW40 || _v_mode == CO40)) #ifdef GRAPH_EX || (_vid_scr.row_q != saverowq || _vid_scr.col_q != savecolq) #endif ) new_size = TRUE; #ifdef GRAPH_EX _csr_enable = FALSE; /* disable cursor */ #endif if (!_vv_init) /* not initialized */ #ifdef MEMEX _dos_extender = _chk_extender(); /* initialize DOS extender stuff */ #else FP_MAKE(_bios_seg, 0x0000, 0x0040); /* We might need it */ #endif #ifdef GRAPH_EX else /* already initialized */ { saverowq = vs_rowq(); /* save current rowq */ savecolq = vs_colq(); /* save current colq */ savetype = _csr_type0; /* get requested cursor type */ if (savetype == -1) /* if already displaying */ savetype = _csr_type1; /* get current cursor type */ if (GRAPHICS) /* if graphics mode */ { /*----------------------------------------------------------------------------*/ /* The following casts are performed so that a FAR pointer (_vid_scr.vbufp) */ /* can be freed as a near pointer without getting any compiler warnings. */ /*----------------------------------------------------------------------------*/ mem_free(*(void **)&_vid_scr.vbufp); /* free video buffer */ mem_free(_scr_buf); /* free screen buffer */ _free_timer(); /* free cursor blink timer */ } } #endif /* GRAPH_EX */ if (setflag) /*Change video mode if requested */ { #ifdef GRAPH_EX /*----------------------------------------------------------------------------*/ /* call current mode's exit function if there is one */ /*----------------------------------------------------------------------------*/ if (_modeexitfp) (*_modeexitfp)(_gmodeelep); /*----------------------------------------------------------------------------*/ /* Modify equipment flag word at 40:10 */ /*----------------------------------------------------------------------------*/ for (i = 0; i < _gmodeq; i++) /* test for graphics modes */ { if (vidmode == _gmodes[i].mode) { flag_mask = _gmodes[i].flagmask; break; } } if (i >= _gmodeq) /* take care of non-graphics modes */ { #endif /*GRAPH_EX */ if (vidmode == MONO || vidmode == 15) /*Set equipment flag_mask value */ flag_mask = MONO_MASK; else if (vidmode < 2) flag_mask = COL40_MASK; else flag_mask = COLOR_MASK; /*assume new mode will be color */ #ifdef GRAPH_EX } #endif /*----------------------------------------------------------------------------*/ /* Modify equipment flag word at 40:10 */ /*----------------------------------------------------------------------------*/ #ifdef GRAPH_EX if (flag_mask != NO_MASK) /*don't change if not specified */ { #endif (*EQUIP_FLAG) &= DISP_MASK; /*clear bits 5 & 6 */ (*EQUIP_FLAG) |= flag_mask; /*turn on bits 5 & 6 for mode */ #ifdef GRAPH_EX } #endif /*----------------------------------------------------------------------------*/ /* set new video mode */ /*----------------------------------------------------------------------------*/ #ifdef GRAPH_EX /*----------------------------------------------------------------------------*/ /* Initialize the Mouse Support */ /* When GraphEx is not in use this initialization is done by vv_init(). */ /* We must move it here to accommodate HGM mode with the mouse */ /* When using MSHERC.COM, this mouse initialization must be done BEFORE */ /* the video mode is set, therefore move it up several statements. */ /*----------------------------------------------------------------------------*/ if (_inittbl[MOUSEINIT]) (*_inittbl[MOUSEINIT])(); if (i < _gmodeq && (modeinitfp = _gmodes[i].modeinitfp)) (*modeinitfp)(&_gmodes[i]); else { /*call BIOS set mode routine */ #endif #ifdef MEMEX vr.ds = vr.es = 0; /* Initialize segment registers */ #endif vr.ax = VI_MODE + vidmode; /*AH = mode set value; AL = mode */ vid_int(&vr, &vr); /*set mode */ #ifdef GRAPH_EX } #endif } /* (setflag) */ if (_vv_init) { /*--------------------------------------------------------------------*/ /* Save window/screen stuff that will be re-initialized by _init_sys.*/ /*--------------------------------------------------------------------*/ copystruct(tfullwn, _fullwn); /*save window structures to be changed*/ copystruct(tvcswn, _vcswn); /*in _inittbl[SYSINIT]() */ copystruct(twn_wn, _wn_wn); copystruct(tmsg_wn, _msgwn); tclratt = _vid_scr.clratt; /*save clear attribute */ /*--------------------------------------------------------------------*/ /* Perform basic system, user, and mouse initialization functions. */ /*--------------------------------------------------------------------*/ tusecount = _vid_scr.usecount; /* Save number of users of _vid_scr. */ if (_inittbl[SYSINIT]) (*_inittbl[SYSINIT])(); _vid_scr.usecount = tusecount; /* New _vid_scr has same # of users */ if (_inittbl[USERINIT]) (*_inittbl[USERINIT])(); if (_inittbl[MOUSEINIT]) (*_inittbl[MOUSEINIT])(); /*--------------------------------------------------------------------*/ /* Restore window/screen stuff that have been changed by _init_sys. */ /*--------------------------------------------------------------------*/ ms_free(FULL_WNP->bufp); /* Get rid of new buffers. Should we */ ms_free(MSG_WNP->bufp); /* wn_free() in case of shad, sbar? */ vs_clratt(tclratt); /*restore clear attribute */ copystruct(_fullwn, tfullwn); /*restore windows possibly changed */ copystruct(_vcswn, tvcswn); /*in _inittbl[SYSINIT]() */ copystruct(_wn_wn, twn_wn); copystruct(_msgwn, tmsg_wn); if (new_size) /*if screen size changing */ { /*resize full screen windows */ MSG_WNP->ref = WN_WNP->ref = _vcswn.ref = FULL_WNP->ref = vs_rowq() - 1; MSG_WNP->cef = WN_WNP->cef = _vcswn.cef = FULL_WNP->cef = vs_colq() - 1; MSG_WNP->rbf = vs_rowq() - 1; _sw_inside(FULL_WNP); wn_msmod(FULL_WNP); _sw_inside(WN_WNP); _sw_inside(&_vcswn); _sw_inside(MSG_WNP); wn_msmod(MSG_WNP); } #ifdef GRAPH_EX /*----------------------------------------------------------------------------*/ /* Restore the cursor type */ /*----------------------------------------------------------------------------*/ csr_type(savetype); #endif } /*end of if (_vv_init) */ #ifdef GRAPH_EX /*----------------------------------------------------------------------------*/ /* Reenable the cursor */ /*----------------------------------------------------------------------------*/ _csr_enable = TRUE; #endif END: if (_vv_init) EXIT_NOERRH(fn); return; }