diff options
Diffstat (limited to 'tvision/classes/dos/dosscr.cc')
-rw-r--r-- | tvision/classes/dos/dosscr.cc | 1004 |
1 files changed, 1004 insertions, 0 deletions
diff --git a/tvision/classes/dos/dosscr.cc b/tvision/classes/dos/dosscr.cc new file mode 100644 index 0000000..f8e1f4e --- /dev/null +++ b/tvision/classes/dos/dosscr.cc @@ -0,0 +1,1004 @@ +/**[txh]******************************************************************** + + DOS Screen (TScreenDOS) functions. + + Copyright (c) 1998-2002 by Salvador E. Tropea (SET) + Contains code Copyright (c) 1996-1998 by Robert H”hne. + + Some code for handling 8x10 fonts is adapted from djgpp libc: + Copyright (C) 1995-1999 DJ Delorie + + Description: + This module implements the low level DOS screen access. + + Configuration variables: + ScreenWidth + ScreenHeight + ScreenPalette + AppCP + ScrCP + InpCP + LoadSecondaryFont + ExtProgVideoMode + VideoMode + VGABIOSState 0 use registers, 1 use BIOS (default) + SaveVGAState 0 don't try to save/restore VGA chip state, + 1 try to save it using the strategy indicated by + VGABIOSState (default) + +***************************************************************************/ + +#include <tv/configtv.h> + +#ifdef TVCompf_djgpp + #include <conio.h> +#endif + +#define Uses_string +#define Uses_unistd +#define Uses_TScreen +#define Uses_TEvent +#define Uses_TGKey +#define Uses_TVOSClipboard +#define Uses_TVCodePage +#include <tv.h> + +// I delay the check to generate as much dependencies as possible +#ifdef TVCompf_djgpp + +#include <dos.h> +#include <malloc.h> +#include <go32.h> +#include <dpmi.h> +#include <sys/farptr.h> +#include <sys/movedata.h> + +#include <pc.h> +#include <stdio.h> +#include <sys/mono.h> + +#define TSCREEN_DEFINE_REGISTERS +#include <tv/dos/screen.h> +#include <tv/dos/key.h> +#include <tv/dos/mouse.h> + +#define GET_DOS_VERSION 0x3000 +#define GET_GLOBAL_CODE_PAGE_TABLE 0x6601 +#define CHARGEN_SET_BLOCK_SPECIFIER 0x1103 +#define CHARGEN_LOAD_USER_SPECIFIED_PATTERNS 0x1110 +#define GET_FONT_INFORMATION 0x1130 +// 0x11xx services (Sets the BIOS Rom) +#define FONT_8x8 0x12 +#define FONT_8x14 0x11 +#define FONT_8x16 0x14 +// GET_FONT_INFORMATION values +#define GET_FONT_8x8 0x03 +#define GET_FONT_8x14 0x02 +#define GET_FONT_8x16 0x06 + +int TScreenDOS::wasBlink=0; +int TScreenDOS::slowScreen=0; +uchar TScreenDOS::primaryFontSet=0, + TScreenDOS::secondaryFontSet=0, + TScreenDOS::fontsSuspended=0; +int TScreenDOS::origCPScr, + TScreenDOS::origCPApp, + TScreenDOS::origCPInp; +int TScreenDOS::fontSeg=-1; +TScreenFont256 TScreenDOS::appFonts[2]={{0,0,NULL},{0,0,NULL}}; + +const unsigned mdaBaseAddress=0xB0000; + +// Extern support functions +extern void SaveScreen(); +extern void SaveScreenReleaseMemory(); +extern void RestoreScreen(); +extern void ScreenUpdate(); +extern ushort user_mode; +extern char useBIOS_VGA_State; +extern char saveVGA_State; + +void setBlinkState(); +void setIntenseState(); +int getBlinkState(); + +TScreen *TV_DOSDriverCheck() +{ + TScreenDOS *drv=new TScreenDOS(); + if (!TScreen::initialized) + { + delete drv; + return 0; + } + return drv; +} + +TScreenDOS::TScreenDOS() +{ + // Currently initialization never fails + initialized=1; + if (dCB) dCB(); + + TDisplayDOS::Init(); + + TScreen::Resume=Resume; + TScreen::Suspend=Suspend; + TScreen::setCrtData=setCrtData; + TScreen::clearScreen=clearScreen; + TScreen::getCharacter=getCharacter; + TScreen::getCharacters=getCharacters; + TScreen::setCharacter=setCharacter; + TScreen::setCharacters=setCharacters; + TScreen::System_p=System; + TScreen::getFontGeometry=GetFontGeometry; + TScreen::setFont_p=SetFont; + TScreen::restoreFonts=RestoreFonts; + + TVDOSClipboard::Init(); + THWMouseDOS::Init(); + TGKeyDOS::Init(); + + long aux; + if (optSearch("VGABIOSState",aux)) + useBIOS_VGA_State=aux; + if (optSearch("SaveVGAState",aux)) + saveVGA_State=aux; + + // Set the code page + int dosCodePage=437; // United States code page, for all versions before 3.3 + // get DOS version number, in the form of a normal number + AX=GET_DOS_VERSION; + dosInt(); + unsigned ver=AH | ((AL & 0xff)<<8); + if (ver>=0x31E) + { + AX=GET_GLOBAL_CODE_PAGE_TABLE; + dosInt(); + dosCodePage=BX; + } + // Look for user settings + optSearch("AppCP",forcedAppCP); + optSearch("ScrCP",forcedScrCP); + optSearch("InpCP",forcedInpCP); + // User settings have more priority than detected settings + codePage=new TVCodePage(forcedAppCP!=-1 ? forcedAppCP : dosCodePage, + forcedScrCP!=-1 ? forcedScrCP : dosCodePage, + forcedInpCP!=-1 ? forcedInpCP : dosCodePage); + SetDefaultCodePages(dosCodePage,dosCodePage,dosCodePage); + + flags0=CodePageVar | CanSetPalette | CanReadPalette | CursorShapes | UseScreenSaver | + CanSetBFont | CanSetSBFont | CanSetVideoSize; + user_mode=startupMode=getCrtMode(); + SaveScreen(); + unsigned startScreenWidth=GetCols(), startScreenHeight=GetRows(); + + unsigned maxX=startScreenWidth, maxY=startScreenHeight; + if (optSearch("ScreenWidth",aux)) + maxX=aux; + if (optSearch("ScreenHeight",aux)) + maxY=aux; + if (frCB) + {// Give a chance to the call back. + primaryFontSet=1; + appFonts[0].h=0; + long aux=0; + if (optSearch("LoadSecondaryFont",aux) && aux) + { + secondaryFontSet=1; + appFonts[1].h=0; + } + } + char *ext=optSearch("ExtProgVideoMode"); + if (optSearch("VideoMode",aux)) + {// if frCB installed it will use the application font + setCrtMode((ushort)aux); + } + else if (ext) + { + setCrtModeExt(ext); + if (frCB) + SelectFont(charLines,False); // Try loading the application font + } + else if (maxX!=startScreenWidth || maxY!=startScreenHeight) + {// if frCB installed it will use the application font + setCrtModeRes(maxX,maxY); + } + else + { + if (frCB) + SelectFont(charLines,False); // Try loading the application font + } + // User requested palette + if (parseUserPalette()) + setPaletteColors(0,16,UserStartPalette); + + screenMode=getCrtMode(); + setCrtData(); + // We use the video memory as buffer, not a malloced buffer + screenBuffer=(uint16 *)-1; + suspended=0; +} + +void TScreenDOS::Resume() +{ + if (!dual_display) + { + GetDisPaletteColors(0,16,OriginalPalette); + SaveScreen(); + //if (screenMode == 0xffff) + // screenMode = getCrtMode(); + if (screenMode!=user_mode) + setCrtMode(screenMode); + if (wasBlink) + setBlinkState(); + else + setIntenseState(); + ResumeFonts(); + SetDisPaletteColors(0,16,ActualPalette); + } + else + { + THWMouseDOS::setEmulation(1); + } + setCrtData(); +} + +TScreenDOS::~TScreenDOS() +{ + suspend(); // First suspend + SaveScreenReleaseMemory(); // Now we can release the memory + ReleaseMemFonts(); + THWMouseDOS::DeInit(); +} + +void TScreenDOS::Suspend() +{ + if (!dual_display) + { + wasBlink=getBlinkState(); + SuspendFonts(); + RestoreScreen(); + SetDisPaletteColors(0,16,OriginalPalette); + } +} + +void TScreenDOS::setCrtData() +{ + if (dual_display) + { + screenMode =7; + screenWidth =80; + screenHeight=25; + cursorLines =0x0b0c; + } + else + { + screenMode =getCrtMode(); + screenWidth =getCols(); + screenHeight=getRows(); + hiResScreen =Boolean(screenHeight>25); + if (screenMode==7) + cursorLines=0x0b0c; // ? + else + cursorLines=getCursorType(); + setCursorType(0); + } +} + +void TScreenDOS::clearScreen() +{ + if (dual_display) + _mono_clear(); // djgpp's libc + else + TDisplay::clearScreen(screenWidth,screenHeight); +} + +ushort TScreenDOS::getCharacter(unsigned offset) +{ + return _farpeekw(_dos_ds,(dual_display ? mdaBaseAddress : ScreenPrimary)+offset*2); +} + +void TScreenDOS::getCharacters(unsigned offset,ushort *buf,unsigned count) +{ + if (slowScreen) + { + _farsetsel(_dos_ds); + int ofs=(dual_display ? mdaBaseAddress : ScreenPrimary)+offset*2; + while (count--) + { + *buf++=_farnspeekw(ofs); + ofs+=2; + } + } + else + { + movedata(_dos_ds,(dual_display ? mdaBaseAddress : ScreenPrimary)+offset*2, + _my_ds(),(int)buf,count*2); + } +} + +void TScreenDOS::setCharacter(unsigned offset,ushort value) +{ + _farpokew(_dos_ds,(dual_display ? mdaBaseAddress : ScreenPrimary)+offset*2,value); +} + +void TScreenDOS::setCharacters(unsigned offset,ushort *values,unsigned count) +{ + if (slowScreen) + { + _farsetsel(_dos_ds); + int ofs = dual_display ? mdaBaseAddress : ScreenPrimary+offset*2; + while (count--) + { + _farnspokew(ofs,*values++); + ofs += 2; + } + } + else + { + movedata(_my_ds(),(int)values,_dos_ds, + (dual_display ? mdaBaseAddress : ScreenPrimary)+offset*2,count*2); + } +} + +int TScreenDOS::System(const char *command, pid_t *pidChild, int in, + int out, int err) +{ + // fork mechanism not available + if (pidChild) + *pidChild=0; + // If the caller asks for redirection replace the requested handles + if (in!=-1) + dup2(in,STDIN_FILENO); + if (out!=-1) + dup2(out,STDOUT_FILENO); + if (err!=-1) + dup2(err,STDERR_FILENO); + return system(command); +} + +/***************************************************************************** + Windows clipboard implementation using WinOldAp API. +*****************************************************************************/ + +#define USE_TB + +// Numbers for the errors +#define WINOLDAP_NoPresent 1 +#define WINOLDAP_ClpInUse 2 +#define WINOLDAP_TooBig 3 +#define WINOLDAP_Memory 4 +#define WINOLDAP_WinErr 5 + +#define WINOLDAP_Errors 5 + +#define IDENTIFY_WinOldAp_VERSION 0x1700 +#define OPEN_CLIPBOARD 0x1701 +#define EMPTY_CLIPBOARD 0x1702 +#define SET_CLIPBOARD_DATA 0x1703 +#define GET_CLIPBOARD_DATA_SIZE 0x1704 +#define GET_CLIPBOARD_DATA 0x1705 +#define CLOSE_CLIPBOARD 0x1708 + +// Strings for the errors +const char *TVDOSClipboard::dosNameError[]= +{ + NULL, + __("Windows not present"), + __("Clipboard in use by other application"), + __("Clipboard too big for the transfer buffer"), + __("Not enough memory"), + __("Windows reports error") +}; + +int TVDOSClipboard::isValid=0; +int TVDOSClipboard::Version; + +int TVDOSClipboard::Init(void) +{ + AX=IDENTIFY_WinOldAp_VERSION; + MultiplexInt(); + Version=AX; + isValid=AX!=IDENTIFY_WinOldAp_VERSION; + if (!isValid) + TVOSClipboard::error=WINOLDAP_NoPresent; + else + { + TVOSClipboard::copy=copy; + TVOSClipboard::paste=paste; + TVOSClipboard::available=1; // We have 1 clipboard + TVOSClipboard::name="Windows"; + TVOSClipboard::errors=WINOLDAP_Errors; + TVOSClipboard::nameErrors=dosNameError; + } + return isValid; +} + +int TVDOSClipboard::AllocateDOSMem(unsigned long size,unsigned long *BaseAddress) +{ + #ifdef USE_TB + unsigned long tbsize=_go32_info_block.size_of_transfer_buffer; + + if (size<=tbsize) + { + *BaseAddress=__tb; + return 1; + } + #endif + if (size>0x100000) + { + TVOSClipboard::error=WINOLDAP_TooBig; + return 0; + } + AH=0x48; + BX=(size>>4)+(size & 0xF ? 1 : 0); + MultiplexInt(); + if (r.x.flags & 1) + { + TVOSClipboard::error=WINOLDAP_TooBig; + return 0; + } + *BaseAddress=AX<<4; + return 1; +} + +void TVDOSClipboard::FreeDOSMem(unsigned long Address) +{ + #ifdef USE_TB + if (Address==__tb) + return; + #endif + AH=0x49; + ES=Address>>4; + TDisplayDOS::dosInt(); +} + +//#define DEBUG_CLIPBOARD +#ifdef DEBUG_CLIPBOARD + ushort messageBox( const char *msg, ushort aOptions ); + ushort messageBox( ushort aOptions, const char *fmt, ... ); + #define DBGMessage(a) messageBox(a,0x402) + #define DBGMessage2(a,b) messageBox(0x402,a,b) +#else + #define DBGMessage(a) + #define DBGMessage2(a,b) +#endif + +int TVDOSClipboard::copy(int id, const char *buffer, unsigned len) +{ + if (!isValid || id!=0) return 0; + + unsigned long dataoff; + char cleaner[32]; + int winLen; + int ret=1; + + AX=OPEN_CLIPBOARD; + MultiplexInt(); + if (AX==0) + { + DBGMessage("Error opening the clipboard"); + TVOSClipboard::error=WINOLDAP_ClpInUse; + return 0; + } + // Erase the current contents of the clipboard + AX=EMPTY_CLIPBOARD; + MultiplexInt(); + winLen=((len+1)+0x1F) & ~0x1F; + memset(cleaner,0,32); + if (AllocateDOSMem(winLen,&dataoff)) + { + dosmemput(buffer,len,dataoff); + dosmemput(cleaner,winLen-len,dataoff+len); + AX=SET_CLIPBOARD_DATA; + DX=7; // OEM text + BX=dataoff & 0x0f; + ES=(dataoff>>4) & 0xffff; + SI=winLen>>16; + CX=winLen & 0xffff; + MultiplexInt(); + FreeDOSMem(dataoff); + if (AX==0) + { + DBGMessage("Error copying to clipboard"); + TVOSClipboard::error=WINOLDAP_WinErr; + ret=0; + } + } + else + { + TVOSClipboard::error=WINOLDAP_Memory; + DBGMessage("Error allocating DOS memory"); + ret=0; + } + AX=CLOSE_CLIPBOARD; + MultiplexInt(); + return ret; +} + +char *TVDOSClipboard::paste(int id, unsigned &len) +{ + if (!isValid || id!=0) return NULL; + + char *p=NULL; + unsigned long BaseAddress; + unsigned long size; + + AX=OPEN_CLIPBOARD; + MultiplexInt(); + if (AX==0) + { + DBGMessage("Error at open clipboard"); + TVOSClipboard::error=WINOLDAP_ClpInUse; + return NULL; + } + AX=GET_CLIPBOARD_DATA_SIZE; + DX=1; + MultiplexInt(); + size=AX+(DX<<16); + DBGMessage2("Size of clipboard %d",size); + if (size) + { + if (AllocateDOSMem(size,&BaseAddress)) + { + p=new char[size]; + if (p) + { + DX=7; + BX=BaseAddress & 0x0f; + ES=(BaseAddress>>4) & 0xffff; + AX=GET_CLIPBOARD_DATA; + MultiplexInt(); + dosmemget(BaseAddress,size,p); + len=strlen(p); + DBGMessage2("Got %d bytes in string",len); + } + else + TVOSClipboard::error=WINOLDAP_Memory; + FreeDOSMem(BaseAddress); + } + else + { + TVOSClipboard::error=WINOLDAP_Memory; + DBGMessage("Error allocating DOS memory"); + } + } + else + { + p=new char[1]; + *p=0; + len=0; + } + AX=CLOSE_CLIPBOARD; + MultiplexInt(); + return p; +} + +/***************************************************************************** + Fonts routines +*****************************************************************************/ + +int TScreenDOS::GetFontGeometry(unsigned &w, unsigned &h) +{ + w=8; + h=charLines; + return 1; +} + +/**[txh]******************************************************************** + + Description: + That selects what fonts are used for no/intense foreground colors.@p + The bits of the call are a little tweaked because it's EGA compatible:@* +---VGA---@* + 0,1,4 block selected by characters with attribute bit 3 clear@* + 2,3,5 block selected by characters with attribute bit 3 set@* + +***************************************************************************/ + +void TScreenDOS::SetDualCharacter(int b1, int b2) +{ + int value; + // No intense foreground font + value=b1 & 0x3; + if (b1 & 0x4) + value|=0x10; + // intense foreground font + value|=(b2 & 0x3)<<2; + if (b2 & 0x4) + value|=0x20; + + AX=CHARGEN_SET_BLOCK_SPECIFIER; + BL=value; + videoInt(); +} + +void TScreenDOS::SetFontBIOS(int which, unsigned height, uchar *data, + int modeRecalculate) +{ + dosmemput(data,256*height,__tb); + ES=__tb>>4; /* pass pointer to our font in ES:BP */ + BP=__tb & 0xF; + DX=0; /* 1st char: ASCII 0 */ + CX=256; /* 256 chars */ + BH=height; /* points per char */ + BL=which; /* block */ + AX=CHARGEN_LOAD_USER_SPECIFIED_PATTERNS; + if (!modeRecalculate) + AL&=0xF; /* force full mode recalculate, service 0x1100 */ + videoInt(); +} + +void TScreenDOS::ReleaseMemFonts() +{ + if (appFonts[0].data) + { + free(appFonts[0].data); + appFonts[0].data=NULL; + } + if (appFonts[1].data) + { + free(appFonts[1].data); + appFonts[1].data=NULL; + } +} + +int TScreenDOS::MemorizeFont(int which, TScreenFont256 *font) +{ + // Keep a copy of the user font + appFonts[which].w=font->w; + appFonts[which].h=font->h; + if (appFonts[which].data) + free(appFonts[which].data); + unsigned size=font->h*256; + appFonts[which].data=(uchar *)malloc(size); + if (!appFonts[which].data) + return 0; + memcpy(appFonts[which].data,font->data,size); + return 1; +} + +void TScreenDOS::SuspendFonts() +{ + if (fontsSuspended) + return; + fontsSuspended=1; + if (!primaryFontSet && !secondaryFontSet) + return; // Nothing to do + DisableDualFont(); + SelectRomFont(charLines,0,0); +} + +void TScreenDOS::ResumeFonts() +{ + if (!fontsSuspended) + return; + fontsSuspended=0; + if (!primaryFontSet && !secondaryFontSet) + return; // Nothing to do + if (primaryFontSet) + SetFontBIOS(0,charLines,appFonts[0].data,0); + if (secondaryFontSet) + { + SetFontBIOS(1,charLines,appFonts[1].data,0); + EnableDualFont(); + } +} + +int TScreenDOS::SetFont(int changeP, TScreenFont256 *fontP, + int changeS, TScreenFont256 *fontS, + int fontCP, int appCP) +{ + if (!changeP && !changeS) return 1; + // Check for restore fonts + if (changeP && !fontP && ((!changeS && !secondaryFontSet) || (changeS && !fontS))) + { + DisableDualFont(); + SelectRomFont(charLines,0,0); + ReleaseMemFonts(); + secondaryFontSet=primaryFontSet=0; + if (fontCP!=-1) + { + if (appCP==-1) + TVCodePage::SetScreenCodePage(fontCP); + else + TVCodePage::SetCodePage(appCP,fontCP,-1); + } + return 1; + } + // Solve the sizes + unsigned wP=8,hP=charLines, + wS=8,hS=charLines; + int newP=changeP && fontP; + if (newP) + { + wP=fontP->w; + hP=fontP->h; + } + int newS=changeS && fontS; + if (newS) + { + wS=fontS->w; + hS=fontS->h; + } + if (wP!=wS || hP!=hS) return 0; + // Check if the size is in the range + if (wP!=8 || hP!=charLines) + return 0; + // Memorize the new fonts + if (newP && !MemorizeFont(0,fontP)) return 0; + if (newS && !MemorizeFont(1,fontS)) return 0; + + // Change the requested fonts + if (changeP) + { + if (!primaryFontSet) + TVCodePage::GetCodePages(origCPApp,origCPScr,origCPInp); + if (fontP) + { + SetFontBIOS(0,charLines,fontP->data,0); + primaryFontSet=1; + } + else + { + SelectRomFont(charLines,0,0); + primaryFontSet=0; + } + } + if (changeS) + { + if (fontS) + { + SetFontBIOS(1,charLines,fontS->data,0); + EnableDualFont(); + secondaryFontSet=1; + } + else + { + DisableDualFont(); + secondaryFontSet=0; + } + } + if (changeP && fontCP!=-1) + { + if (appCP==-1) + TVCodePage::SetScreenCodePage(fontCP); + else + TVCodePage::SetCodePage(appCP,fontCP,-1); + } + return 1; +} + +void TScreenDOS::RestoreFonts() +{ + if (!primaryFontSet && !secondaryFontSet) + return; // Protection + SetFont(1,NULL,1,NULL,origCPScr,origCPApp); +} + +/**[txh]******************************************************************** + + Description: + Selects a font of the desired size. Currently only 8x8, 8x10, 8x14 and +8x16 are supported but I did it in this way because nobody knows about the +future.@p + If noForce is != 0 then the routine doesn't set the fonts. This option +must be used when you know that BIOS already loaded the fonts. Using it +avoids an extra load. The derived classes takes the desition according to +the selected font, so if the user selected a font the load is forced.@p + If modeRecalculate is 1 the call to set the BIOS font is made using the +bit 4 on, that means the BIOS will recalculate some things like the number +of rows and cols in the screen. That's avoided when an external program +sets the mode because a recalculation can fail.@p + + Return: + non-zero if fails, zero if all ok. + +***************************************************************************/ + +int TScreenDOS::SelectRomFont(int height, int which, int modeRecalculate) +{ + //UseDefaultFontsNextTime=0; + switch (height) + { + case 8: + SetRomFonts(FONT_8x8,which,modeRecalculate); + break; + case 10: + if (Load8x10Font(which,modeRecalculate)) + return 1; + break; + case 14: + SetRomFonts(FONT_8x14,which,modeRecalculate); + break; + case 16: + SetRomFonts(FONT_8x16,which,modeRecalculate); + break; + default: + return 1; + } + return 0; +} + +void TScreenDOS::SetRomFonts(int sizeFont, int which, int modeRecalculate) +{ + if (!modeRecalculate) + sizeFont&=0xF; + BL=which; + AH=0x11; + AL=sizeFont; + videoInt(); +} + + +/**[txh]******************************************************************** + + Description: + Stretch a 8x8 font to the 8x10 character box. This is required to +use 80x40 mode on a VGA or 80x35 mode on an EGA, because the character +box is 10 lines high, and the ROM BIOS doesn't have an appropriate font. +So we create one from the 8x8 font by adding an extra blank line +from each side. + +***************************************************************************/ + +void TScreenDOS::MaybeCreate8x10Font(void) +{ + unsigned char *p; + unsigned long src, dest, i, j; + + if (fontSeg!=-1) + return; + int buf_pm_sel; + + /* Allocate buffer in conventional memory. */ + fontSeg=__dpmi_allocate_dos_memory(160,&buf_pm_sel); + + if (fontSeg==-1) + return; + + /* Get the pointer to the 8x8 font table. */ + p=(uchar *)malloc(2560); /* 256 chars X 8x10 pixels */ + if (p==(uchar *)0) + { + //errno=ENOMEM; + __dpmi_free_dos_memory(buf_pm_sel); + fontSeg=-1; + return; + } + BH=GET_FONT_8x8; + AX=GET_FONT_INFORMATION; + videoInt(); + src=(((unsigned)ES)<<4)+BP; + dest=((unsigned)fontSeg)<<4; + + /* Now copy the font to our table, stretching it to 8x10. */ + _farsetsel(_dos_ds); + for (i=0; i<256; i++) + { + /* Fill first extra scan line with zeroes. */ + _farnspokeb(dest++, 0); + + for (j=0; j<8; j++) + { + uchar val=_farnspeekb(src++); + _farnspokeb(dest++,val); + } + + /* Fill last extra scan line with zeroes. */ + _farnspokeb(dest++,0); + } +} + +/* Load the 8x10 font we created into character generator RAM. */ +int TScreenDOS::Load8x10Font(int which, int modeRecalculate) +{ + MaybeCreate8x10Font(); /* create if needed */ + if (fontSeg==-1) + return 1; + ES=fontSeg; /* pass pointer to our font in ES:BP */ + BP=0; + DX=0; /* 1st char: ASCII 0 */ + CX=256; /* 256 chars */ + BH=10; /* 10 points per char */ + BL=which; /* block */ + AX=CHARGEN_LOAD_USER_SPECIFIED_PATTERNS; + if (!modeRecalculate) + AL&=0xF; + videoInt(); + return 0; +} + +/**[txh]******************************************************************** + + Description: + Used after setting a video mode to load the user font or the BIOS font. +The force parameter indicates if we must load the BIOS font or if the font +was already loaded.@p + If a font was set the application this function tries to reuse it. If the +font doesn't match the size used by the video mode calls a call back +requesting a new font. If the routine fails to get a propper font the BIOS +font is restored. + +***************************************************************************/ + +void TScreenDOS::SelectFont(unsigned height, Boolean Force) +{ + int fontWasLoaded=primaryFontSet || secondaryFontSet; + + if (primaryFontSet && !fontsSuspended) + { + if (height==appFonts[0].h) + SetFontBIOS(0,height,appFonts[0].data,0); + else + { + int fontOk=0; + // The one provided by the application isn't suitable + if (frCB) + {// Try asking the application to provide a new one + TScreenFont256 *font=frCB(0,8,height); + if (font) + { + SetFontBIOS(0,height,font->data,0); + MemorizeFont(0,font); + fontOk=1; + DeleteArray(font->data); + delete font; + } + } + if (!fontOk) + { + if (Force) + SelectRomFont(height,0,1); + primaryFontSet=0; + } + } + } + else + { + if (Force) + SelectRomFont(height,0,1); + } + + if (!fontsSuspended && secondaryFontSet) + { + if (height==appFonts[1].h) + SetFontBIOS(1,height,appFonts[1].data,0); + else + { + int fontOk=0; + // The one provided by the application isn't suitable + if (frCB) + {// Try asking the application to provide a new one + TScreenFont256 *font=frCB(1,8,height); + if (font) + { + SetFontBIOS(1,height,font->data,0); + MemorizeFont(1,font); + fontOk=1; + DeleteArray(font->data); + delete font; + } + } + if (!fontOk) + { + DisableDualFont(); + secondaryFontSet=0; + } + } + } + + if (fontWasLoaded && !(primaryFontSet || secondaryFontSet)) + // Restore the original encoding if we forced ROM fonts + TVCodePage::SetCodePage(origCPApp,origCPScr,origCPInp); +} + + +#else // DJGPP + +#include <tv/dos/screen.h> +#include <tv/dos/key.h> +#include <tv/dos/mouse.h> + +#endif // else DJGPP + |