1049 lines
24 KiB
C++
1049 lines
24 KiB
C++
// This may look like C code, but it is really -*- C++ -*-
|
|
|
|
// ------------------------------------------------------------------
|
|
// The Goldware Library
|
|
// Copyright (C) 1990-1999 Odinn Sorensen
|
|
// Copyright (C) 1999-2000 Alexander S. Aganichev
|
|
// Copyright (C) 2000 Jacobo Tarrio
|
|
// ------------------------------------------------------------------
|
|
// This library is free software; you can redistribute it and/or
|
|
// modify it under the terms of the GNU Library General Public
|
|
// License as published by the Free Software Foundation; either
|
|
// version 2 of the License, or (at your option) any later version.
|
|
//
|
|
// This library is distributed in the hope that it will be useful,
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
// Library General Public License for more details.
|
|
//
|
|
// You should have received a copy of the GNU Library General Public
|
|
// License along with this program; if not, write to the Free
|
|
// Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
|
// MA 02111-1307, USA
|
|
// ------------------------------------------------------------------
|
|
// $Id$
|
|
// ------------------------------------------------------------------
|
|
// Device-independent video functions
|
|
// ------------------------------------------------------------------
|
|
|
|
#include <cstdio>
|
|
#include <cstdlib>
|
|
#include <cstdarg>
|
|
#include <gmemall.h>
|
|
#include <gmemdbg.h>
|
|
#include <gstrall.h>
|
|
#if defined(__WATCOMC__) || defined(__DJGPP__)
|
|
#include <conio.h>
|
|
#endif
|
|
#include <gvidall.h>
|
|
|
|
#if defined(__OS2__)
|
|
#define INCL_BASE
|
|
#include <os2.h>
|
|
#endif
|
|
|
|
#if defined(__WIN32__)
|
|
#include <windows.h>
|
|
#endif
|
|
|
|
#if !defined(__USE_NCURSES__) && defined(__UNIX__)
|
|
#include <sys/ioctl.h>
|
|
#include <termios.h>
|
|
#include <unistd.h>
|
|
#include <errno.h>
|
|
#endif
|
|
|
|
#if defined(__DJGPP__)
|
|
#include <sys/farptr.h>
|
|
#include <go32.h>
|
|
#endif
|
|
|
|
|
|
// ------------------------------------------------------------------
|
|
// Check if Borland C++ for OS/2 1.0 header has been fixed
|
|
|
|
#if defined(__OS2__) && defined(__BORLANDC__)
|
|
#if __BORLANDC__ <= 0x400
|
|
#ifndef BCOS2_BSESUB_FIXED
|
|
#error There is a bug in the BSESUB.H header. Please fix it.
|
|
//
|
|
// Add/change the following in BSESUB.H:
|
|
//
|
|
// #define BCOS2_BSESUB_FIXED
|
|
// APIRET16 APIENTRY16 VioGetState (PVOID16 pState, HVIO hvio);
|
|
// APIRET16 APIENTRY16 VioSetState (PVOID16 pState, HVIO hvio);
|
|
//
|
|
// Borland forgot this (was only PVOID) ^^
|
|
//
|
|
#endif
|
|
#endif
|
|
#endif
|
|
|
|
|
|
// ------------------------------------------------------------------
|
|
// Global video data
|
|
|
|
GVid *gvid;
|
|
|
|
#if defined(__USE_NCURSES__)
|
|
|
|
// add statics here
|
|
|
|
#elif defined(__UNIX__)
|
|
|
|
int gvid_stdout = -1;
|
|
const char* gvid_acs_enable;
|
|
const char* gvid_acs_disable;
|
|
|
|
void _vputx(int row, int col, int atr, char chr, uint len);
|
|
void gvid_printf(const char* fmt, ...) __attribute__ ((format (printf, 1, 2)));
|
|
|
|
#elif defined(__WIN32__)
|
|
|
|
HANDLE gvid_hout = INVALID_HANDLE_VALUE;
|
|
|
|
#elif defined(__MSDOS__)
|
|
|
|
int __gdvdetected = false;
|
|
|
|
#endif
|
|
|
|
|
|
// ------------------------------------------------------------------
|
|
// Video Class constructor
|
|
|
|
GVid::GVid() {
|
|
|
|
#ifdef __DJGPP__
|
|
dmaptr = dmadir = 0;
|
|
#else
|
|
dmaptr = dmadir = NULL;
|
|
#endif
|
|
bufchr = NULL;
|
|
bufwrd = NULL;
|
|
bufansi = NULL;
|
|
|
|
init();
|
|
}
|
|
|
|
|
|
// ------------------------------------------------------------------
|
|
// Video Class destructor
|
|
|
|
GVid::~GVid() {
|
|
|
|
#if defined(__USE_NCURSES__)
|
|
|
|
attrset(A_NORMAL);
|
|
if(0 == (--curses_initialized))
|
|
endwin();
|
|
|
|
#elif defined(__UNIX__)
|
|
|
|
// "\033<" Enter ANSI mode
|
|
// "\033[?5l" Normal screen
|
|
// "\033[0m" Normal character attributes
|
|
|
|
gvid_printf("\033<\033[?5l\033[0m");
|
|
|
|
#endif
|
|
#ifndef __DJGPP__
|
|
if(dmaptr != dmadir) throw_xfree(dmaptr);
|
|
#endif
|
|
throw_xfree(bufwrd);
|
|
throw_xfree(bufchr);
|
|
throw_xfree(bufansi);
|
|
}
|
|
|
|
|
|
// ------------------------------------------------------------------
|
|
|
|
void GVid::init() {
|
|
|
|
#if defined(__USE_NCURSES__)
|
|
// Both display and keyboard will be initialized at once
|
|
if(0 == (curses_initialized++)) {
|
|
initscr();
|
|
raw();
|
|
noecho();
|
|
nonl();
|
|
intrflush(stdscr, FALSE);
|
|
keypad(stdscr, TRUE);
|
|
}
|
|
#endif
|
|
|
|
// Detect video adapter
|
|
detectadapter();
|
|
|
|
// Detect original video information
|
|
detectinfo(&orig);
|
|
memcpy(&curr, &orig, sizeof(GVidInfo));
|
|
|
|
#if defined(__MSDOS__)
|
|
device = GVID_DMA;
|
|
#elif defined(__OS2__)
|
|
device = GVID_OS2;
|
|
#elif defined(__WIN32__)
|
|
device = GVID_W32;
|
|
#endif
|
|
|
|
#if defined(__USE_NCURSES__)
|
|
dmaptr = dmadir = NULL;
|
|
#elif defined(__WATCOMC__) && defined(__386__)
|
|
dmaptr = dmadir = (gdma)(videoseg << 4);
|
|
#elif defined(__DJGPP__)
|
|
dmaptr = dmadir = ScreenPrimary;
|
|
#elif defined(__OS2__) || defined(__WIN32__)
|
|
dmaptr = dmadir = NULL;
|
|
#elif defined(__UNIX__)
|
|
dmaptr = (gdma)throw_xcalloc((orig.screen.rows+1)*orig.screen.columns, sizeof(word));
|
|
dmadir = NULL;
|
|
#else
|
|
dmaptr = dmadir = (gdma)MK_FP(videoseg, 0);
|
|
#endif
|
|
|
|
bufchr = NULL;
|
|
bufwrd = NULL;
|
|
bufansi = NULL;
|
|
|
|
resetcurr();
|
|
}
|
|
|
|
// ------------------------------------------------------------------
|
|
// Video adapter detect
|
|
|
|
int GVid::detectadapter() {
|
|
|
|
// Initialize to a valid value
|
|
adapter = GV_NONE;
|
|
|
|
#if defined(__USE_NCURSES__)
|
|
|
|
start_color();
|
|
|
|
/* init colors */
|
|
short mycolors[] = { COLOR_BLACK, COLOR_BLUE, COLOR_GREEN, COLOR_CYAN,
|
|
COLOR_RED, COLOR_MAGENTA, COLOR_YELLOW, COLOR_WHITE };
|
|
for(int i = 1; i < 64 and i < COLOR_PAIRS; i++)
|
|
init_pair(i, mycolors[(~i)&0x07], mycolors[(i>>3)&0x07]);
|
|
|
|
adapter = V_VGA;
|
|
|
|
#elif defined(__MSDOS__)
|
|
|
|
i86 cpu;
|
|
|
|
// Get video mode
|
|
cpu.ah(V_GET_MODE);
|
|
cpu.genint(0x10);
|
|
int _got_mode = cpu.al();
|
|
|
|
// Check for PS/2 compatible video BIOS by calling the get
|
|
// video configuration function. If it exists, the video
|
|
// configuration code will be returned in BL.
|
|
|
|
cpu.ax(0x1A00);
|
|
cpu.genint(0x10);
|
|
|
|
if(cpu.al() == 0x1A) {
|
|
|
|
switch(cpu.bl()) {
|
|
case 0x00:
|
|
adapter = GV_NONE;
|
|
break;
|
|
case 0x01:
|
|
adapter = V_MDA;
|
|
break;
|
|
case 0x02:
|
|
adapter = V_CGA;
|
|
break;
|
|
case 0x04:
|
|
adapter = V_EGA;
|
|
break;
|
|
case 0x05:
|
|
adapter = V_EGAMONO;
|
|
break;
|
|
case 0x07:
|
|
adapter = (_got_mode == 7) ? V_VGAMONO : V_VGA;
|
|
break;
|
|
case 0x08:
|
|
adapter = (_got_mode == 7) ? V_VGAMONO : V_VGA;
|
|
break;
|
|
case 0x0A:
|
|
case 0x0C:
|
|
adapter = V_MCGA;
|
|
break;
|
|
case 0x0B:
|
|
adapter = V_MCGAMONO;
|
|
break;
|
|
default:
|
|
adapter = V_VGA; // We hope it is VGA compatible!
|
|
}
|
|
}
|
|
else {
|
|
|
|
// OK, we know that it's not a PS/2 BIOS, so check for an EGA.
|
|
// If an EGA is not present, BH will be unchanged on return.
|
|
|
|
cpu.ah(0x12);
|
|
cpu.bl(0x10);
|
|
cpu.genint(0x10);
|
|
|
|
if(cpu.bl() - 0x10) {
|
|
adapter = cpu.bh() ? V_EGAMONO : V_EGA;
|
|
}
|
|
else {
|
|
|
|
// Now we know it's not an EGA. Get the BIOS equipment
|
|
// flag and test for CGA, MDA, or no video adapter.
|
|
|
|
cpu.genint(0x11);
|
|
|
|
switch(cpu.al() & 0x30) {
|
|
case 0x00:
|
|
adapter = (_got_mode == 7) ? V_VGAMONO : V_VGA; // EGA, VGA, or PGA
|
|
break;
|
|
case 0x10:
|
|
adapter = GV_NONE; // 40x25 color
|
|
break;
|
|
case 0x20:
|
|
adapter = V_CGA; // 80x25 color
|
|
break;
|
|
case 0x30:
|
|
adapter = V_MDA; // 80x25 monochrome
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
#ifndef __DJGPP__
|
|
|
|
// Set video segment
|
|
#if defined(__BORLANDC__) && defined(__DPMI32__)
|
|
videoseg = (word)((adapter & V_MONO) ? __SegB000 : __SegB800);
|
|
#else
|
|
videoseg = (word)((adapter & V_MONO) ? 0xB000 : 0xB800);
|
|
#endif
|
|
|
|
// check for presence of DESQview by using the DOS Set
|
|
// System Date function and trying to set an invalid date
|
|
|
|
cpu.ax(0x2B01); // DOS Set System Date
|
|
cpu.ch('D');
|
|
cpu.cl('E');
|
|
cpu.dh('S');
|
|
cpu.dl('Q');
|
|
cpu.genint(0x21);
|
|
|
|
// if error, then DESQview not present
|
|
if(cpu.al() != 0xFF) {
|
|
|
|
__gdvdetected = true;
|
|
|
|
#if defined(__WATCOMC__) && defined(__386__)
|
|
memset(&RMI, 0, sizeof(RMI));
|
|
RMI.EAX = 0x0000FE00;
|
|
RMI.ES = videoseg;
|
|
cpu.ax(0x0300);
|
|
cpu.bl(0x10);
|
|
cpu.bh(0);
|
|
cpu.cx(0);
|
|
cpu.es(FP_SEG(&RMI));
|
|
cpu.edi(FP_OFF(&RMI));
|
|
cpu.genint(0x31);
|
|
videoseg = RMI.ES;
|
|
#else
|
|
cpu.ah(0xFE); // DV get alternate video buffer
|
|
cpu.es(videoseg);
|
|
cpu.di(0x0000);
|
|
cpu.genint(0x10);
|
|
videoseg = cpu.es();
|
|
#endif
|
|
}
|
|
|
|
#endif // __DJGPP__
|
|
|
|
#elif defined(__OS2__)
|
|
|
|
{
|
|
VIOCONFIGINFO vioconfiginfo;
|
|
memset(&vioconfiginfo, 0, sizeof(VIOCONFIGINFO));
|
|
vioconfiginfo.cb = sizeof(VIOCONFIGINFO);
|
|
VioGetConfig(0, &vioconfiginfo, 0);
|
|
switch(vioconfiginfo.adapter) {
|
|
case DISPLAY_MONOCHROME:
|
|
adapter = V_MDA;
|
|
break;
|
|
case DISPLAY_CGA:
|
|
adapter = V_CGA;
|
|
break;
|
|
case DISPLAY_EGA:
|
|
adapter = V_EGA;
|
|
break;
|
|
case DISPLAY_VGA:
|
|
adapter = V_VGA;
|
|
break;
|
|
default:
|
|
adapter = V_VGA; // We hope it is VGA compatible!
|
|
}
|
|
if(vioconfiginfo.display == DISPLAY_MONOCHROME)
|
|
adapter |= V_MONO;
|
|
}
|
|
|
|
#elif defined(__WIN32__)
|
|
|
|
gvid_hout = CreateFile("CONOUT$", GENERIC_READ | GENERIC_WRITE,
|
|
FILE_SHARE_WRITE | FILE_SHARE_READ, NULL,
|
|
OPEN_EXISTING,
|
|
FILE_FLAG_NO_BUFFERING|FILE_FLAG_WRITE_THROUGH, NULL);
|
|
|
|
adapter = V_VGA;
|
|
|
|
#elif defined(__linux__)
|
|
|
|
for(int n=0; n<8; n++)
|
|
__box_table[n] = __box_table[8];
|
|
|
|
gvid_acs_enable = "\016";
|
|
gvid_acs_disable = "\017";
|
|
|
|
gvid_stdout = fileno(stdout);
|
|
|
|
adapter = V_VGA;
|
|
|
|
#elif defined(__UNIX__) // code below should not be normally used...
|
|
|
|
bool gvid_xterm = false;
|
|
const char* term = getenv("TERM");
|
|
|
|
if(term and strneql(term, "xterm", 5)) {
|
|
gvid_xterm = true;
|
|
for(int n=0; n<8; n++)
|
|
__box_table[n] = __box_table[8];
|
|
}
|
|
|
|
gvid_acs_enable = gvid_xterm ? "\033)0\033(B\016" : "\033[11m";
|
|
gvid_acs_disable = gvid_xterm ? "\033(B\033)B\017" : "\033[10m";
|
|
|
|
gvid_stdout = fileno(stdout);
|
|
|
|
adapter = V_VGA;
|
|
|
|
#endif
|
|
|
|
return adapter;
|
|
}
|
|
|
|
|
|
// ------------------------------------------------------------------
|
|
// Video info detect
|
|
|
|
void GVid::detectinfo(GVidInfo* _info) {
|
|
|
|
// Reset all original values
|
|
memset(_info, 0, sizeof(GVidInfo));
|
|
|
|
#if defined(__USE_NCURSES__)
|
|
|
|
_info->screen.mode = 0;
|
|
_info->screen.rows = LINES;
|
|
_info->screen.columns = COLS;
|
|
getyx(stdscr, _info->cursor.row, _info->cursor.column);
|
|
_info->color.textattr = 7;
|
|
_info->cursor.start = 11;
|
|
_info->cursor.end = 12;
|
|
_info->cursor.attr = 7;
|
|
_info->color.intensity = 1;
|
|
_info->color.overscan = 0;
|
|
|
|
#elif defined(__MSDOS__)
|
|
|
|
i86 cpu;
|
|
|
|
// Get video mode and number of columns
|
|
cpu.ah(V_GET_MODE);
|
|
cpu.genint(0x10);
|
|
_info->screen.mode = cpu.al();
|
|
_info->screen.columns = cpu.ah();
|
|
|
|
// Get the number of screen rows
|
|
if(adapter >= V_EGA) {
|
|
cpu.ax(V_GET_FONT_INFO);
|
|
cpu.dx(0);
|
|
cpu.genint(0x10);
|
|
_info->screen.rows = cpu.dl() + ((adapter & V_EGA) ? 0 : 1);
|
|
if(_info->screen.rows == 24) // Normally nonsense
|
|
_info->screen.rows++;
|
|
//_info->screen.cheight = cpu.cx();
|
|
_info->screen.cheight = 8;
|
|
_info->screen.cwidth = 8;
|
|
}
|
|
else {
|
|
_info->screen.rows = 25;
|
|
_info->screen.cheight = 8;
|
|
_info->screen.cwidth = 8;
|
|
}
|
|
|
|
// Get character attribute under the cursor
|
|
cpu.ah(V_RD_CHAR_ATTR);
|
|
cpu.bh(0);
|
|
cpu.genint(0x10);
|
|
_info->color.textattr = cpu.ah();
|
|
|
|
// Get cursor position and form
|
|
cpu.ah(V_GET_CURSOR_POS);
|
|
cpu.bh(0);
|
|
cpu.genint(0x10);
|
|
_info->cursor.row = cpu.dh();
|
|
_info->cursor.column = cpu.dl();
|
|
_info->cursor.start = cpu.ch();
|
|
_info->cursor.end = cpu.cl();
|
|
_info->cursor.attr = (word)_info->color.textattr;
|
|
// Get overscan color
|
|
if(adapter & V_VGA) {
|
|
cpu.ax(0x1008);
|
|
cpu.bh(0xFF);
|
|
cpu.genint(0x10);
|
|
_info->color.overscan = cpu.bh();
|
|
}
|
|
|
|
// Get intensity state
|
|
{
|
|
// Check bit 5 at 0000:0465
|
|
#if defined(__DJGPP__)
|
|
_info->color.intensity = (_farpeekb (_dos_ds, 0x465) & 0x20) ? 0 : 1;
|
|
#else
|
|
byte* _bptr = (byte*)0x0465;
|
|
_info->color.intensity = (*_bptr & 0x20) ? 0 : 1;
|
|
#endif
|
|
|
|
}
|
|
|
|
#elif defined(__OS2__)
|
|
|
|
// Get video mode and number of rows and columns
|
|
{
|
|
VIOMODEINFO viomodeinfo;
|
|
memset(&viomodeinfo, 0, sizeof(VIOMODEINFO));
|
|
viomodeinfo.cb = sizeof(VIOMODEINFO);
|
|
VioGetMode(&viomodeinfo, 0);
|
|
_info->screen.mode = viomodeinfo.fbType;
|
|
_info->screen.rows = viomodeinfo.row;
|
|
_info->screen.columns = viomodeinfo.col;
|
|
_info->screen.cheight = viomodeinfo.vres / viomodeinfo.row;
|
|
_info->screen.cwidth = viomodeinfo.hres / viomodeinfo.col;
|
|
}
|
|
|
|
// Get cursor position and character attribute under the cursor
|
|
{
|
|
USHORT usRow, usColumn;
|
|
VioGetCurPos(&usRow, &usColumn, 0);
|
|
_info->cursor.row = usRow;
|
|
_info->cursor.column = usColumn;
|
|
BYTE chat[2];
|
|
USHORT len = 2;
|
|
#if defined(__EMX__)
|
|
VioReadCellStr((PCH)chat, &len, usRow, usColumn, 0);
|
|
#else
|
|
VioReadCellStr((CHAR*)chat, &len, usRow, usColumn, 0);
|
|
#endif
|
|
_info->color.textattr = chat[1];
|
|
}
|
|
|
|
// Get cursor form
|
|
{
|
|
VIOCURSORINFO viocursorinfo;
|
|
memset(&viocursorinfo, 0, sizeof(VIOCURSORINFO));
|
|
VioGetCurType(&viocursorinfo, 0);
|
|
_info->cursor.start = viocursorinfo.yStart;
|
|
_info->cursor.end = viocursorinfo.cEnd;
|
|
_info->cursor.attr = viocursorinfo.attr;
|
|
}
|
|
|
|
// Get intensity state
|
|
{
|
|
VIOINTENSITY viointensity;
|
|
memset(&viointensity, 0, sizeof(VIOINTENSITY));
|
|
viointensity.cb = sizeof(VIOINTENSITY);
|
|
viointensity.type = 0x0002;
|
|
VioGetState(&viointensity, 0);
|
|
_info->color.intensity = viointensity.fs ? 1 : 0;
|
|
}
|
|
|
|
// Get overscan color
|
|
{
|
|
VIOOVERSCAN viooverscan;
|
|
memset(&viooverscan, 0, sizeof(VIOOVERSCAN));
|
|
viooverscan.cb = sizeof(VIOOVERSCAN);
|
|
viooverscan.type = 0x0001;
|
|
VioGetState(&viooverscan, 0);
|
|
_info->color.overscan = (int)viooverscan.color;
|
|
}
|
|
|
|
#elif defined(__WIN32__)
|
|
|
|
// Get video mode and number of rows and columns
|
|
CONSOLE_SCREEN_BUFFER_INFO csbi;
|
|
assert(GetConsoleScreenBufferInfo(gvid_hout, &csbi) != 0);
|
|
|
|
_info->screen.mode = 0;
|
|
_info->screen.rows = csbi.dwSize.Y;
|
|
_info->screen.columns = csbi.dwSize.X;
|
|
|
|
// Get cursor position and character attribute under the cursor
|
|
_info->cursor.row = csbi.dwCursorPosition.Y;
|
|
_info->cursor.column = csbi.dwCursorPosition.X;
|
|
_info->color.textattr = csbi.wAttributes;
|
|
|
|
if(_info->screen.rows > 100) {
|
|
_info->screen.rows = csbi.srWindow.Bottom - csbi.srWindow.Top + 1;
|
|
_info->screen.columns = csbi.srWindow.Right - csbi.srWindow.Left + 1;
|
|
_info->cursor.row = csbi.dwCursorPosition.Y - csbi.srWindow.Top + 1;
|
|
_info->cursor.column = csbi.dwCursorPosition.X - csbi.srWindow.Left + 1;
|
|
}
|
|
|
|
// Get cursor form
|
|
CONSOLE_CURSOR_INFO cci;
|
|
GetConsoleCursorInfo(gvid_hout, &cci);
|
|
|
|
_info->cursor.start = (int) 1;
|
|
_info->cursor.end = cci.bVisible ? (int) 15 : 0;
|
|
_info->cursor.attr = (word)(cci.bVisible ? 7 : 0);
|
|
|
|
// Get intensity state
|
|
_info->color.intensity = 1;
|
|
|
|
// Get overscan color
|
|
_info->color.overscan = 0;
|
|
|
|
#elif defined(__UNIX__)
|
|
|
|
int r = 0, c = 0;
|
|
|
|
if(r <= 0) {
|
|
char *s = getenv("LINES");
|
|
if(s) {
|
|
//printf("getenv(\"LINES\") = %s\n", s);
|
|
r = atoi(s);
|
|
}
|
|
}
|
|
|
|
if(c <= 0) {
|
|
char *s = getenv("COLUMNS");
|
|
if(s) {
|
|
//printf("getenv(\"COLUMNS\") = %s\n", s);
|
|
c = atoi(s);
|
|
}
|
|
}
|
|
|
|
//printf("init1: c=%i, r=%i\n", c, r);
|
|
|
|
#if defined(TIOCGSIZE)
|
|
if(r <= 0 or c <= 0) {
|
|
struct ttysize sz;
|
|
|
|
do {
|
|
if((ioctl(1,TIOCGSIZE,&sz) == 0) or (ioctl(0, TIOCGSIZE, &sz) == 0) or (ioctl(2, TIOCGSIZE, &sz) == 0)) {
|
|
c = (int)sz.ts_cols;
|
|
r = (int)sz.ts_lines;
|
|
break;
|
|
}
|
|
} while(errno == EINTR);
|
|
}
|
|
//printf("init2: c=%i, r=%i\n", c, r);
|
|
#elif defined(TIOCGWINSZ)
|
|
if(r <= 0 or c <= 0) {
|
|
struct winsize wind_struct;
|
|
|
|
do {
|
|
if((ioctl(1,TIOCGWINSZ,&wind_struct) == 0) or (ioctl(0, TIOCGWINSZ, &wind_struct) == 0) or (ioctl(2, TIOCGWINSZ, &wind_struct) == 0)) {
|
|
c = (int)wind_struct.ws_col;
|
|
r = (int)wind_struct.ws_row;
|
|
break;
|
|
}
|
|
} while(errno == EINTR);
|
|
}
|
|
//printf("init3: c=%i, r=%i\n", c, r);
|
|
#endif
|
|
|
|
|
|
if((r <= 0) or (r > 200))
|
|
r = 24;
|
|
if((c <= 0) or (c > 250))
|
|
c = 80;
|
|
|
|
//printf("init4: c=%i, r=%i\n", c, r);
|
|
|
|
//*dmadir = 0;
|
|
|
|
_info->screen.mode = 0;
|
|
_info->screen.rows = r;
|
|
_info->screen.columns = c;
|
|
_info->cursor.row = 0;
|
|
_info->cursor.column = 0;
|
|
_info->color.textattr = 7;
|
|
_info->cursor.start = 11;
|
|
_info->cursor.end = 12;
|
|
_info->cursor.attr = 7;
|
|
_info->color.intensity = 1;
|
|
_info->color.overscan = 0;
|
|
|
|
#endif
|
|
|
|
getpalette(_info->color.palette);
|
|
}
|
|
|
|
|
|
// ------------------------------------------------------------------
|
|
// Reset current video info
|
|
|
|
void GVid::resetcurr() {
|
|
|
|
currow = curr.cursor.row;
|
|
curcol = curr.cursor.column;
|
|
|
|
numrows = curr.screen.rows;
|
|
numcols = curr.screen.columns;
|
|
|
|
throw_xfree(bufchr);
|
|
throw_xfree(bufwrd);
|
|
throw_xfree(bufansi);
|
|
|
|
bufchr = (vchar*)throw_xcalloc(sizeof(vchar), numcols+1);
|
|
bufwrd = (vatch*)throw_xcalloc(sizeof(vatch), numcols+1);
|
|
bufansi = (vchar*)throw_xcalloc(sizeof(vchar), (11*numcols)+1);
|
|
|
|
setdevice(device);
|
|
}
|
|
|
|
|
|
// ------------------------------------------------------------------
|
|
// Sets video output device
|
|
|
|
void GVid::setdevice(int _device) {
|
|
|
|
device = _device;
|
|
}
|
|
|
|
|
|
// ------------------------------------------------------------------
|
|
// Sets video mode
|
|
|
|
void GVid::setmode(int _mode) {
|
|
|
|
if(_mode) {
|
|
#if defined(__MSDOS__)
|
|
|
|
i86 cpu;
|
|
cpu.ah(0x00);
|
|
cpu.al((byte)_mode);
|
|
cpu.genint(0x10);
|
|
|
|
#endif
|
|
}
|
|
|
|
detectinfo(&curr);
|
|
resetcurr();
|
|
}
|
|
|
|
|
|
// ------------------------------------------------------------------
|
|
// Sets screen rows
|
|
|
|
void GVid::setrows(int _rows) {
|
|
|
|
int origrows = curr.screen.rows;
|
|
|
|
#if defined(__USE_NCURSES__)
|
|
|
|
NW(_rows);
|
|
|
|
#elif defined(__MSDOS__)
|
|
i86 cpu;
|
|
|
|
// Set video mode 3 (80xNN)
|
|
if(curr.screen.mode != 3) {
|
|
cpu.ax(0x0003);
|
|
cpu.genint(0x10);
|
|
}
|
|
|
|
if(adapter >= V_EGA) {
|
|
if((_rows == 28) and (adapter >= V_VGA)) { // vga-only
|
|
cpu.ax(0x1202);
|
|
cpu.bl(0x30);
|
|
cpu.genint(0x10);
|
|
cpu.ax(0x1111);
|
|
cpu.bl(0);
|
|
cpu.genint(0x10);
|
|
}
|
|
else if(_rows >= 43) {
|
|
cpu.ax(0x1112); // Load 8x8 character set
|
|
cpu.bl(0x00);
|
|
cpu.genint(0x10);
|
|
cpu.ax(0x1200); // Select alternate print-screen routine
|
|
cpu.bl(0x20);
|
|
cpu.genint(0x10);
|
|
if(adapter & V_EGA) {
|
|
// Disable cursor size emulation
|
|
byte* _bptr = (byte*)0x0487;
|
|
*_bptr |= (byte)0x01;
|
|
// Set cursor size
|
|
cpu.ah(0x01);
|
|
cpu.al((byte)orig.screen.mode);
|
|
cpu.cx(0x0600);
|
|
cpu.genint(0x10);
|
|
}
|
|
}
|
|
else {
|
|
if(adapter & V_EGA) {
|
|
// Enable cursor size emulation
|
|
byte* _bptr = (byte*)0x0487;
|
|
*_bptr &= (byte)0xFE;
|
|
}
|
|
// Set cursor size
|
|
cpu.ah(0x01);
|
|
cpu.al((byte)orig.screen.mode);
|
|
cpu.cx(0x0607);
|
|
cpu.genint(0x10);
|
|
}
|
|
}
|
|
|
|
#elif defined(__OS2__)
|
|
|
|
VIOMODEINFO viomodeinfo;
|
|
memset(&viomodeinfo, 0, sizeof(VIOMODEINFO));
|
|
viomodeinfo.cb = sizeof(VIOMODEINFO);
|
|
VioGetMode(&viomodeinfo, 0);
|
|
viomodeinfo.row = (USHORT)_rows;
|
|
VioSetMode(&viomodeinfo, 0);
|
|
|
|
#elif defined(__WIN32__) || defined(__UNIX__)
|
|
|
|
NW(_rows);
|
|
|
|
#endif
|
|
|
|
if(origrows < _rows)
|
|
vfill(origrows, 0, _rows, 80, ' ', 7);
|
|
|
|
detectinfo(&curr);
|
|
resetcurr();
|
|
}
|
|
|
|
|
|
// ------------------------------------------------------------------
|
|
// Set the screen border (overscan) color
|
|
|
|
void GVid::setoverscan(int _overscan) {
|
|
|
|
#if defined(__USE_NCURSES__)
|
|
|
|
NW (_overscan);
|
|
|
|
#elif defined(__MSDOS__)
|
|
|
|
i86 cpu;
|
|
cpu.ah(0x0B);
|
|
cpu.bh(0x00);
|
|
cpu.bl((byte)_overscan);
|
|
cpu.genint(0x10);
|
|
|
|
#elif defined(__OS2__)
|
|
|
|
VIOOVERSCAN viooverscan;
|
|
memset(&viooverscan, 0, sizeof(VIOOVERSCAN));
|
|
viooverscan.cb = sizeof(VIOOVERSCAN);
|
|
viooverscan.type = 0x0001;
|
|
VioGetState(&viooverscan, 0);
|
|
viooverscan.color = (BYTE)_overscan;
|
|
VioSetState(&viooverscan, 0);
|
|
|
|
#elif defined(__WIN32__) || defined(__UNIX__)
|
|
|
|
NW(_overscan);
|
|
|
|
#endif
|
|
}
|
|
|
|
|
|
// ------------------------------------------------------------------
|
|
// Set intensity/blinking state
|
|
|
|
void GVid::setintensity(int _intensity) {
|
|
|
|
#if defined(__USE_NCURSES__)
|
|
|
|
NW(_intensity);
|
|
|
|
#elif defined(__MSDOS__)
|
|
|
|
#ifdef __DJGPP__
|
|
|
|
if(_intensity)
|
|
intensevideo();
|
|
else
|
|
blinkvideo();
|
|
|
|
#else
|
|
|
|
if(adapter & V_CGA) {
|
|
word* _wptr = (word*)0x0463;
|
|
byte* _bptr = (byte*)0x0465;
|
|
uint port = *_wptr + 4;
|
|
uint reg = *_bptr;
|
|
if(_intensity)
|
|
reg &= 0xDF;
|
|
else
|
|
reg |= 0x20;
|
|
outp(port, reg);
|
|
}
|
|
else {
|
|
i86 cpu;
|
|
cpu.ax(0x1003);
|
|
cpu.bh(0x00);
|
|
cpu.bl((byte)(_intensity ? 0 : 1));
|
|
cpu.genint(0x10);
|
|
}
|
|
|
|
#endif // __DJGPP__
|
|
|
|
#elif defined(__OS2__)
|
|
|
|
VIOINTENSITY viointensity;
|
|
memset(&viointensity, 0, sizeof(VIOINTENSITY));
|
|
viointensity.cb = sizeof(VIOINTENSITY);
|
|
viointensity.fs = (USHORT)(_intensity ? 1 : 0);
|
|
viointensity.type = 0x0002;
|
|
VioSetState(&viointensity, 0);
|
|
|
|
#elif defined(__WIN32__) || defined(__UNIX__)
|
|
|
|
NW(_intensity);
|
|
|
|
#endif
|
|
}
|
|
|
|
|
|
// ------------------------------------------------------------------
|
|
|
|
void GVid::getpalette(int* _palette) {
|
|
|
|
#if defined(__USE_NCURSES__)
|
|
|
|
NW(_palette);
|
|
|
|
#elif defined(__MSDOS__)
|
|
|
|
// Get palette state
|
|
if(adapter & V_VGA) {
|
|
i86 cpu;
|
|
for(byte n=0; n<16; n++) {
|
|
cpu.ax(0x1007); // GET INDIVIDUAL PALETTE REGISTER
|
|
cpu.bh(0xFF);
|
|
cpu.bl(n);
|
|
cpu.genint(0x10);
|
|
_palette[n] = cpu.bh();
|
|
}
|
|
}
|
|
else {
|
|
// Set to standard palette colors
|
|
for(byte n=0; n<16; n++)
|
|
_palette[n] = n + ((n > 7) ? 48 : 0);
|
|
}
|
|
|
|
#elif defined(__OS2__)
|
|
|
|
// Get palette state
|
|
BYTE viopalstate[38];
|
|
PVIOPALSTATE pviopalstate;
|
|
memset(viopalstate, 0, sizeof(viopalstate));
|
|
pviopalstate = (PVIOPALSTATE)viopalstate;
|
|
pviopalstate->cb = sizeof(viopalstate);
|
|
pviopalstate->type = 0;
|
|
pviopalstate->iFirst = 0;
|
|
VioGetState(pviopalstate, 0);
|
|
for(byte n=0; n<16; n++)
|
|
_palette[n] = pviopalstate->acolor[n];
|
|
|
|
#elif defined(__WIN32__) || defined(__UNIX__)
|
|
|
|
NW(_palette);
|
|
|
|
#endif
|
|
}
|
|
|
|
|
|
// ------------------------------------------------------------------
|
|
|
|
void GVid::setpalette(int* _palette) {
|
|
|
|
#if defined(__USE_NCURSES__)
|
|
|
|
NW(_palette);
|
|
|
|
#elif defined(__MSDOS__)
|
|
|
|
if(adapter & (V_EGA|V_MCGA|V_VGA)) {
|
|
i86 cpu;
|
|
for(byte n=0; n<16; n++) {
|
|
if(_palette[n] != -1) {
|
|
cpu.ax(0x1000);
|
|
cpu.bl(n);
|
|
cpu.bh((byte)_palette[n]);
|
|
cpu.genint(0x10);
|
|
}
|
|
}
|
|
}
|
|
|
|
#elif defined(__OS2__)
|
|
|
|
BYTE viopalstate[38];
|
|
PVIOPALSTATE pviopalstate;
|
|
memset(viopalstate, 0, sizeof(viopalstate));
|
|
pviopalstate = (PVIOPALSTATE)viopalstate;
|
|
pviopalstate->cb = sizeof(viopalstate);
|
|
pviopalstate->type = 0;
|
|
pviopalstate->iFirst = 0;
|
|
VioGetState(pviopalstate, 0);
|
|
for(byte n=0; n<16; n++)
|
|
if(_palette[n] != -1)
|
|
pviopalstate->acolor[n] = (USHORT)_palette[n];
|
|
VioSetState(pviopalstate, 0);
|
|
|
|
#elif defined(__WIN32__) || defined(__UNIX__)
|
|
|
|
NW(_palette);
|
|
|
|
#endif
|
|
}
|
|
|
|
|
|
// ------------------------------------------------------------------
|
|
|
|
void GVid::restore_cursor() {
|
|
|
|
vcurset(orig.cursor.start, orig.cursor.end);
|
|
vcurshow();
|
|
vposset(orig.cursor.row-1, 0);
|
|
}
|
|
|
|
|
|
// ------------------------------------------------------------------
|
|
|
|
void GVid::resize_screen(int columns, int rows) {
|
|
|
|
numcols = curr.screen.columns = columns;
|
|
numrows = curr.screen.rows = rows;
|
|
|
|
bufchr = (vchar*)throw_xrealloc(bufchr, numcols+1);
|
|
bufwrd = (vatch*)throw_xrealloc(bufwrd, (numcols+1)*sizeof(vatch));
|
|
bufansi = (vchar*)throw_xrealloc(bufansi, 1+(11*numcols));
|
|
|
|
#if defined(__UNIX__) && !defined(__USE_NCURSES__)
|
|
dmaptr = (gdma)throw_xrealloc(dmaptr, (rows+1)*columns*sizeof(word));
|
|
#endif
|
|
}
|
|
|
|
|
|
// ------------------------------------------------------------------
|