This repository has been archived on 2024-04-08. You can view files and clone it, but cannot push or open issues or pull requests.
deb-goldedplus/goldlib/gall/gvidbase.cpp

2179 lines
50 KiB
C++
Raw Normal View History

2000-02-25 10:15:17 +00:00
// 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>
#include <gvidall.h>
#if defined(__OS2__)
#define INCL_BASE
#include <os2.h>
#ifndef __EMX__
#define PCCH CHAR*
#endif
#endif
#ifdef __WIN32__
#include <windows.h>
#endif
#ifdef __GNUC__
#include <unistd.h>
#endif
#if defined(__DJGPP__)
#include <sys/farptr.h>
#endif
// ------------------------------------------------------------------
// Check if Borland C++ for OS/2 1.0 header has been fixed
2001-04-15 19:24:44 +00:00
#if defined(__OS2__) && defined(__BORLANDC__)
2000-02-25 10:15:17 +00:00
#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
// ------------------------------------------------------------------
static bool __vcurhidden = false;
#if defined(__UNIX__) || defined(__USE_NCURSES__)
static uint32_t gvid_boxcvtc(char);
#endif
2000-02-25 10:15:17 +00:00
2001-04-15 19:24:44 +00:00
#if !defined(__USE_NCURSES__)
2000-02-25 10:15:17 +00:00
// ------------------------------------------------------------------
#ifdef __WIN32__
extern HANDLE gvid_hout;
extern OSVERSIONINFO WinVer; // defined in gutlwin.cpp
extern WCHAR oem2unicode[]; // defined in gutlwin.cpp
// ------------------------------------------------------------------
// Transform character < 32 into printable Unicode equivalent
inline WCHAR gvid_tcpr(vchar chr) {
2004-01-20 14:58:37 +00:00
return oem2unicode[chr & 0xff];
}
2000-02-25 10:15:17 +00:00
#endif
// ------------------------------------------------------------------
2001-04-15 19:24:44 +00:00
#if defined(__MSDOS__) || defined(__UNIX__)
2000-02-25 10:15:17 +00:00
#if defined(__MSDOS__)
extern int __gdvdetected;
#endif
2000-02-25 10:15:17 +00:00
#ifndef __DJGPP__
const unsigned short _dos_ds = 0;
inline unsigned short _my_ds(void) {
return 0;
}
inline void _farpokew(unsigned short s, gdma ptr, word chat) {
NW(s);
*ptr = chat;
}
inline void _farnspokew(gdma ptr, word chat) {
*ptr = chat;
}
inline word _farpeekw(unsigned short s, gdma ptr) {
NW(s);
return *ptr;
}
inline void _farnspokeb(byte *ptr, byte chr) {
*ptr = chr;
}
inline void _farsetsel(unsigned short s) {
NW(s);
}
#endif
#ifdef __DJGPP__
const int ATTRSIZE = sizeof(word);
#else
const int ATTRSIZE = 1;
#endif
inline void gdmacpy(unsigned short seg_d, gdma sel_d, unsigned short seg_s, gdma sel_s, int len) {
#ifdef __DJGPP__
movedata(seg_s, sel_s, seg_d, sel_d, len);
#else
NW(seg_d);
NW(seg_s);
memcpy(sel_d, sel_s, len);
#endif
}
inline gdma gdmaptr(int col, int row) {
return gvid->dmaptr+ATTRSIZE*((row*gvid->numcols)+col);
}
#endif
// ------------------------------------------------------------------
#if defined(__UNIX__)
// ------------------------------------------------------------------
extern int gvid_stdout;
extern const char* gvid_acs_enable;
extern const char* gvid_acs_disable;
int gvid_last_attr = 0;
// ------------------------------------------------------------------
void gvid_printf(const char* fmt, ...) {
char buf[1024];
va_list argptr;
va_start(argptr, fmt);
int n = vsprintf(buf, fmt, argptr);
va_end(argptr);
write(gvid_stdout, buf, n);
}
// ------------------------------------------------------------------
// Control chars 01234567890123456789012345678901
const char* gvid_x0 = "x@xxxxxxxxxxxxxx><xxxxxx^vxxxx^v";
// ------------------------------------------------------------------
inline void gvid_cvtchr(char& ch) {
register const char* x0 = gvid_x0;
if(ch < ' ')
ch = x0[ch];
}
// ------------------------------------------------------------------
void gvid_cvtstr(char* s, int len) {
register char* p = s;
for(int n=0; n<len; n++,p++)
gvid_cvtchr(*p);
}
// ------------------------------------------------------------------
void gvid_cvtstr(word* ws, int len) {
register word* wp = ws;
for(int n=0; n<len; n++,wp++)
gvid_cvtchr(*(char*)wp);
}
// ------------------------------------------------------------------
static int _atr_to_ans[8] = {
0, // BLACK 0
4, // BLUE 1
2, // GREEN 2
6, // CYAN 3
1, // RED 4
5, // MAGENTA 5
3, // BROWN 6
7 // WHITE 7
};
// ------------------------------------------------------------------
inline int vatr2ansin(int x) {
return (x & 8) ? 1 : 0;
}
// ------------------------------------------------------------------
inline int vatr2ansfg(int x) {
return _atr_to_ans[x & 7];
}
// ------------------------------------------------------------------
inline int vatr2ansbg(int x) {
return _atr_to_ans[(x>>4) & 7];
}
// ------------------------------------------------------------------
void vputansi(int row, int col, word* buf, int len) {
char ch;
int in, fg, bg, acs;
int atr = gvid_last_attr;
int in0 = vatr2ansin(atr);
int fg0 = vatr2ansfg(atr);
int bg0 = vatr2ansbg(atr);
int acs0 = atr & ACSET;
// Get pointer to ANSI line buffer
char* ptr = gvid->bufansi;
// Get pointer to video memory image
byte* p = (byte*)buf;
for(int n=0; n<len; n++,p+=2) { // For each screen element
if(p[1] != atr) { // If attribute is different
atr = p[1]; // Store new attribute
gvid_last_attr = atr;
in = vatr2ansin(atr); // Get intensity
fg = vatr2ansfg(atr); // Get foreground color
bg = vatr2ansbg(atr); // Get background color
acs = atr & ACSET; // Get Alt Color Set
if(acs != acs0) {
ptr = stpcpy(ptr, acs ? gvid_acs_enable : gvid_acs_disable);
acs0 = acs;
}
*ptr++ = 0x1B; // Start ANSI color sequence
*ptr++ = '[';
if(in != in0) { // Set intensity if different
if(in)
*ptr++ = '1'; // Intense
else {
*ptr++ = '0'; // Reset
fg0 = bg0 = -1;
}
in0 = in;
if((fg != fg0) or (bg != bg0))
*ptr++ = ';';
}
if(fg != fg0) { // Set foreground if different
*ptr++ = '3';
*ptr++ = (char)('0' + fg);
fg0 = fg;
if(bg != bg0)
*ptr++ = ';';
}
if(bg != bg0) { // Set background if different
*ptr++ = '4';
*ptr++ = (char)('0' + bg);
bg0 = bg;
}
*ptr++ = 'm'; // End ANSI color sequence
}
ch = p[0];
gvid_cvtchr(ch);
*ptr++ = ch; // Output the character
}
*ptr = NUL; // Terminate string
// Print complete ANSI string at the specified position
gvid_printf("\x1B[%u;%uH%s", row+1, col+1, gvid->bufansi);
}
// ------------------------------------------------------------------
#endif
2001-04-15 19:24:44 +00:00
#endif // !defined(__USE_NCURSES__)
2000-02-25 10:15:17 +00:00
// ------------------------------------------------------------------
// Converts an attribute to monochrome equivalent
int mapattr(int attr) {
switch(attr&112) { // test for a light background
case _LGREY:
case _GREEN:
case _CYAN:
case _BROWN:
attr &= 240; // foreground = black
attr |= 112; // background = light grey
break;
default:
if((attr&15)==8) // if foreground = dark grey
attr &= 247; // clear intensity bit
attr |= 7; // foreground = light grey
attr &= 143; // background = black
}
return attr; // return converted attribute
}
// ------------------------------------------------------------------
// Reverses the attribute given
int revsattr(int attr) {
return (int)(((attr>>4)&0x07)|((attr<<4)&0x70)|(attr&0x80)|(attr&0x08));
}
2001-04-15 19:24:44 +00:00
#if !defined(__USE_NCURSES__)
2000-02-25 10:15:17 +00:00
// ------------------------------------------------------------------
#if defined(__UNIX__)
char* gvid_newattr(int& attr) {
// 12345678901234567890
// E[1;33;44mE[11m
static char newattr[20];
*newattr = NUL;
if(attr != gvid_last_attr) {
if((attr & ~ACSET) != (gvid_last_attr & ~ACSET)) {
sprintf(newattr, "\033[%c;3%u;4%um",
vatr2ansin(attr) ? '1' : '0',
vatr2ansfg(attr),
vatr2ansbg(attr)
);
}
if((attr & ACSET) != (gvid_last_attr & ACSET))
strcat(newattr, (attr & ACSET) ? gvid_acs_enable : gvid_acs_disable);
gvid_last_attr = attr;
}
return newattr;
}
#endif
// ------------------------------------------------------------------
// OS/2 Vio* wrappers for prevent 16-bit segment overrun
#if defined(__OS2__)
#ifndef _THUNK_PTR_SIZE_OK
#define _THUNK_PTR_SIZE_OK(ptr,size) (((ULONG)(ptr) & ~0xffff) == (((ULONG)(ptr) + (size) - 1) & ~0xffff))
#endif
static USHORT VioReadCellStr_(PCH str, PUSHORT pcb, USHORT row, USHORT col, HVIO hvio) {
USHORT rc, cb = *pcb;
if(_THUNK_PTR_SIZE_OK(str, cb))
return VioReadCellStr(str, pcb, row, col, hvio);
PCH newstr = (PCH)throw_xmalloc(cb * 2);
if(_THUNK_PTR_SIZE_OK(newstr, cb)) {
rc = VioReadCellStr(newstr, pcb, row, col, hvio);
if(rc == 0)
memcpy(str, newstr, *pcb);
}
else {
rc = VioReadCellStr(newstr + cb, pcb, row, col, hvio);
if(rc == 0)
memcpy(str, newstr + cb, *pcb);
}
throw_xfree(newstr);
return rc;
}
static USHORT VioWrtCellStr_(PCCH str, USHORT cb, USHORT row, USHORT col, HVIO hvio) {
USHORT rc;
if(_THUNK_PTR_SIZE_OK(str, cb ))
return VioWrtCellStr(str, cb, row, col, hvio);
PCH newstr = (PCH)throw_xmalloc(cb * 2);
if(_THUNK_PTR_SIZE_OK(newstr, cb)) {
memcpy(newstr, str, cb);
rc = VioWrtCellStr(newstr, cb, row, col, hvio);
}
else {
memcpy(newstr + cb, str, cb);
rc = VioWrtCellStr(newstr + cb, cb, row, col, hvio);
}
throw_xfree(newstr);
return rc;
}
static USHORT VioWrtCharStrAtt_(PCCH str, USHORT cb, USHORT row, USHORT col, PBYTE attr, HVIO hvio) {
USHORT rc;
if(_THUNK_PTR_SIZE_OK(str, cb))
return VioWrtCharStrAtt(str, cb, row, col, attr, hvio);
PCH newstr = (PCH)throw_xmalloc(cb * 2);
if(_THUNK_PTR_SIZE_OK(newstr, cb)) {
memcpy(newstr, str, cb);
rc = VioWrtCharStrAtt(newstr, cb, row, col, attr, hvio);
}
else {
memcpy(newstr + cb, str, cb);
rc = VioWrtCharStrAtt(newstr + cb, cb, row, col, attr, hvio);
}
throw_xfree(newstr);
return rc;
}
#define VioReadCellStr VioReadCellStr_
#define VioWrtCellStr VioWrtCellStr_
#define VioWrtCharStrAtt VioWrtCharStrAtt_
#endif
// ------------------------------------------------------------------
// ncurses support functions
#else // defined(__USE_NCURSES__)
// ------------------------------------------------------------------
// Compute our attributes from DOS attributes
int gvid_attrcalc(int dosattr) {
2000-02-25 10:15:17 +00:00
// DOS attrs: XRGBxrgb
// color pair definition: 00RGBrgb, with last 3 bits negated
int attr;
attr = COLOR_PAIR(((dosattr & 0x70) >> 1) | ((~dosattr) & 0x07));
if(dosattr & 0x08)
attr |= A_BOLD;
// if(dosattr & 0x80)
// attr |= A_BLINK;
return attr;
}
// ------------------------------------------------------------------
// Compute DOS attributes from our attributes
int gvid_dosattrcalc(int ourattr) {
2000-02-25 10:15:17 +00:00
int attr = 0;
attr = PAIR_NUMBER(ourattr);
attr = ((attr & 0x38) << 1) | ((~attr) & 0x07);
if(ourattr & A_BLINK)
attr |= 0x80;
if(ourattr & A_BOLD)
attr |= 0x08;
return attr;
}
// ------------------------------------------------------------------
// Transform character < 32 into printable equivalent
chtype gvid_tcpr(vchar chr) {
2000-02-25 10:15:17 +00:00
const chtype gvid_cpr[] = {
(chtype)' ', (chtype)'@', (chtype)'@', (chtype)'x',
(chtype) ACS_DIAMOND, (chtype)'x', (chtype)'x', ACS_BULLET,
ACS_BULLET, ACS_BULLET, ACS_BULLET, (chtype)'x',
(chtype)'x', (chtype)'x', (chtype)'x', ACS_LANTERN,
(chtype)ACS_RARROW, ACS_LARROW, (chtype)'x', (chtype)'!',
(chtype)'x', (chtype)'x', ACS_S1, (chtype)'x',
ACS_UARROW, ACS_DARROW, ACS_LARROW, (chtype)ACS_RARROW,
(chtype)'x', (chtype)'x', ACS_UARROW, ACS_DARROW
};
2000-02-25 10:15:17 +00:00
chtype ch = chr & A_CHARTEXT;
chtype at = chr & (~A_CHARTEXT);
if(ch<' ')
return gvid_cpr[ch] | at;
else
return ch | at;
}
// ------------------------------------------------------------------
#endif // defined(__USE_NCURSES__)
// ------------------------------------------------------------------
// Print character and attribute at specfied location
2001-04-15 19:24:44 +00:00
#if (defined(__MSDOS__) || defined(__UNIX__)) && !defined(__USE_NCURSES__)
2000-02-25 10:15:17 +00:00
inline void _vputw(int row, int col, word chat) {
_farpokew(_dos_ds, gdmaptr(col, row), chat);
}
#endif
void vputw(int row, int col, vatch chat) {
#if defined(__USE_NCURSES__)
mvaddch(row, col, chat);
refresh();
#elif defined(__MSDOS__)
if(gvid->isdma()) {
_vputw(row, col, chat);
}
else if(gvid->isbios() or gvid->iscga()) {
i86 cpu;
cpu.ah(2);
cpu.bh(0);
cpu.dh((byte)row);
cpu.dl((byte)col);
cpu.genint(0x10);
cpu.ah(9);
cpu.al(vgchar(chat));
2000-02-25 10:15:17 +00:00
cpu.bh(0);
cpu.bl(vgattr(chat));
2000-02-25 10:15:17 +00:00
cpu.cx(1);
cpu.genint(0x10);
}
#elif defined(__OS2__)
VioWrtNCell((BYTE *)&chat, 1, (USHORT)row, (USHORT)col, 0);
2000-02-25 10:15:17 +00:00
#elif defined(__WIN32__)
const COORD coord = {0, 0};
const COORD size = {1, 1};
SMALL_RECT rect;
2000-02-25 10:15:17 +00:00
rect.Top = row;
rect.Left = col;
rect.Bottom = row+size.Y-1;
rect.Right = col+size.X-1;
if(WinVer.dwPlatformId == VER_PLATFORM_WIN32_NT) {
chat.Char.UnicodeChar = gvid_tcpr(vgchar(chat));
WriteConsoleOutputW(gvid_hout, &chat, size, coord, &rect);
}
else
WriteConsoleOutputA(gvid_hout, &chat, size, coord, &rect);
2000-02-25 10:15:17 +00:00
#elif defined(__UNIX__)
char chr = vgchar(chat);
int atr = vgattr(chat);
2000-02-25 10:15:17 +00:00
char* color = gvid_newattr(atr);
gvid_cvtstr(&chat, 1);
_vputw(row, col, chat);
gvid_printf("\033[%u;%uH%s%c", row+1, col+1, color, chr);
#endif
}
// ------------------------------------------------------------------
// Print attrib/char buffer at specfied location
void vputws(int row, int col, vatch* buf, uint len) {
#if defined(__USE_NCURSES__)
move(row, col);
for(int counter = 0; counter < len; counter++)
addch(buf[counter]);
refresh();
#elif defined(__MSDOS__)
if(gvid->isdma()) {
gdmacpy(_dos_ds, (gdma)gdmaptr(col, row), _my_ds(), (gdma)buf, len*sizeof(word));
}
else if(gvid->isbios() or gvid->iscga()) {
i86 cpu;
byte* p = (byte*)buf;
for(uint n=0; n<len; n++) {
cpu.ah(2);
cpu.bh(0);
cpu.dh((byte)row);
cpu.dl((byte)col++);
cpu.genint(0x10);
cpu.ah(9);
cpu.al(*p++);
cpu.bh(0);
cpu.bl(*p++);
cpu.cx(1);
cpu.genint(0x10);
}
}
#elif defined(__OS2__)
VioWrtCellStr((PCCH)buf, (USHORT)(len*2), (USHORT)row, (USHORT)col, 0);
#elif defined(__WIN32__)
const COORD coord = {0, 0};
COORD size = {len, 1};
SMALL_RECT rect;
rect.Top = row;
rect.Left = col;
rect.Bottom = row+size.Y-1;
rect.Right = col+size.X-1;
if(WinVer.dwPlatformId == VER_PLATFORM_WIN32_NT) {
for(int i = 0; i < len; i++) {
buf[i].Char.UnicodeChar = gvid_tcpr(vgchar(buf[i]));
}
WriteConsoleOutputW(gvid_hout, buf, size, coord, &rect);
2000-02-25 10:15:17 +00:00
}
else
WriteConsoleOutputA(gvid_hout, buf, size, coord, &rect);
2000-02-25 10:15:17 +00:00
#elif defined(__UNIX__)
gvid_cvtstr(buf, len);
gdmacpy(_dos_ds, (gdma)gdmaptr(col, row), _my_ds(), (gdma)buf, len*sizeof(word));
vputansi(row, col, buf, len);
#endif
}
// ------------------------------------------------------------------
// Print character and attribute at specfied location
void vputc(int row, int col, int atr, vchar chr) {
#if defined(__USE_NCURSES__)
mvaddch(row, col, vcatch(gvid_tcpr(chr), atr));
2000-02-25 10:15:17 +00:00
refresh();
#elif defined(__MSDOS__)
if(gvid->isdma()) {
_vputw(row, col, vcatch(chr, atr));
2000-02-25 10:15:17 +00:00
}
else if(gvid->isbios() or gvid->iscga()) {
i86 cpu;
cpu.ah(2);
cpu.bh(0);
cpu.dh((byte)row);
cpu.dl((byte)col);
cpu.genint(0x10);
cpu.ah(9);
cpu.al(chr);
cpu.bh(0);
cpu.bl((byte)atr);
cpu.cx(1);
cpu.genint(0x10);
}
2001-04-15 19:24:44 +00:00
#elif defined(__OS2__) || defined(__WIN32__)
2000-02-25 10:15:17 +00:00
vputw(row, col, vcatch(chr, atr));
2000-02-25 10:15:17 +00:00
#elif defined(__UNIX__)
char* color = gvid_newattr(atr);
gvid_cvtstr(&chr, 1);
_vputw(row, col, vcatch(chr, atr));
2000-02-25 10:15:17 +00:00
gvid_printf("\033[%u;%uH%s%c", row+1, col+1, color, chr);
#endif
}
// ------------------------------------------------------------------
// Print string with attribute at specfied location
void vputvs(int row, int col, int atr, const vchar* str) {
#if defined(__USE_NCURSES__)
uint counter;
int attr = gvid_attrcalc(atr);
move(row, col);
for(counter = 0; str[counter] != 0; counter++)
addch(gvid_tcpr(str[counter]) | attr);
refresh();
#else
2000-02-25 10:15:17 +00:00
vputs(row, col, atr, str);
#endif
2000-02-25 10:15:17 +00:00
}
// ------------------------------------------------------------------
// Print string with attribute at specfied location
2001-07-25 19:06:12 +00:00
void vputs_box(int row, int col, int atr, const char* str) {
#if defined(__USE_NCURSES__)
uint counter;
int len = strlen(str);
int attr = gvid_attrcalc(atr);
move(row, col);
for(counter = 0; counter < len; counter++)
addch(gvid_tcpr(gvid_boxcvtc(str[counter])) | attr);
refresh();
#else
vputs(row, col, atr, str);
#endif
}
2000-02-25 10:15:17 +00:00
void vputs(int row, int col, int atr, const char* str) {
#if defined(__USE_NCURSES__)
uint counter;
int len = strlen(str);
int attr = gvid_attrcalc(atr);
move(row, col);
for(counter = 0; counter < len; counter++)
addch(gvid_tcpr(str[counter]) | attr);
refresh();
#elif defined(__MSDOS__)
if(gvid->isdma()) {
gdma p = gdmaptr(col, row);
_farsetsel(_dos_ds);
while(*str) {
_farnspokew(p, vcatch(*str++, atr));
2000-02-25 10:15:17 +00:00
p += ATTRSIZE;
}
}
else if(gvid->isbios() or gvid->iscga()) {
i86 cpu;
for(const char* q=str; *q; q++) {
// Write as fast as possible on XT bios...
cpu.ah(2);
cpu.bh(0);
cpu.dh((byte)row);
cpu.dl((byte)(col++));
cpu.genint(0x10);
cpu.ah(9);
cpu.al(*q);
cpu.bh(0);
cpu.bl((byte)atr);
cpu.cx(1);
cpu.genint(0x10);
}
}
#elif defined(__OS2__)
VioWrtCharStrAtt((PCCH)str, (USHORT)strlen(str), (USHORT)row, (USHORT)col, (PBYTE)&atr, 0);
#elif defined(__WIN32__)
int i;
2000-02-25 10:15:17 +00:00
for(i = 0; *str; i++)
gvid->bufwrd[i] = vcatch(*str++, atr);
if(i)
vputws(row, col, gvid->bufwrd, i);
2000-02-25 10:15:17 +00:00
#elif defined(__UNIX__)
char buf[1024];
strcpy(buf, str);
char* color = gvid_newattr(atr);
gvid_cvtstr(buf, strlen(buf));
gdma p = gdmaptr(col, row);
_farsetsel(_dos_ds);
while(*str) {
_farnspokew(p, vcatch(*str++, atr));
2000-02-25 10:15:17 +00:00
p += ATTRSIZE;
}
gvid_printf("\033[%u;%uH%s%s", row+1, col+1, color, buf);
#endif
}
// ------------------------------------------------------------------
// Print string with attribute at specfied location
2001-04-15 19:24:44 +00:00
#if (defined(__MSDOS__) || defined(__UNIX__)) && !defined(__USE_NCURSES__)
2000-02-25 10:15:17 +00:00
static void _vputns(int row, int col, int atr, const char* str, uint width) {
char fillchar = ' ';
gdma p = gdmaptr(col, row);
_farsetsel(_dos_ds);
while(width--) {
_farnspokew(p, (atr << 8) | (*str ? *str++ : fillchar));
p += ATTRSIZE;
}
}
#endif
// ------------------------------------------------------------------
// Print string with attribute at specfied location
void vputns(int row, int col, int atr, const char* str, uint width) {
char fillchar = ' ';
#if defined(__USE_NCURSES__)
uint counter;
int len = strlen(str);
int attr = gvid_attrcalc(atr);
move(row, col);
for(counter = 0; counter < width; counter++) {
if(counter<len)
addch(gvid_tcpr(str[counter]) | attr);
else
addch(gvid_tcpr(fillchar) | attr);
}
refresh();
#elif defined(__MSDOS__)
if(gvid->isdma()) {
_vputns(row, col, atr, str, width);
}
else if(gvid->isbios() or gvid->iscga()) {
i86 cpu;
while(width--) {
// Write as fast as possible on XT bios...
cpu.ah(2);
cpu.bh(0);
cpu.dh((byte)row);
cpu.dl((byte)(col++));
cpu.genint(0x10);
cpu.ah(9);
cpu.al(*str ? *str++ : fillchar);
cpu.bh(0);
cpu.bl((byte)atr);
cpu.cx(1);
cpu.genint(0x10);
}
}
#elif defined(__OS2__)
uint len = strlen(str);
VioWrtCharStrAtt((PCCH)str, (USHORT)minimum_of_two(len,width), (USHORT)row, (USHORT)col, (PBYTE)&atr, 0);
if(width > len) {
vatch filler = vcatch(fillchar, atr);
VioWrtNCell((BYTE *)&filler, (USHORT)(width-len), (USHORT)row, (USHORT)(col+len), 0);
2000-02-25 10:15:17 +00:00
}
#elif defined(__WIN32__)
int i;
2000-02-25 10:15:17 +00:00
for(i = 0; (i < width) and *str; i++)
gvid->bufwrd[i] = vcatch(*str++, atr);
vatch filler = vcatch(fillchar, atr);
for(; i < width; i++)
gvid->bufwrd[i] = filler;
vputws(row, col, gvid->bufwrd, width);
2000-02-25 10:15:17 +00:00
#elif defined(__UNIX__)
char* color = gvid_newattr(atr);
uint len = strlen(str);
uint min_len = minimum_of_two(len, width);
char buf[1024];
strcpy(buf, str);
gvid_cvtstr(buf, len);
_vputns(row, col, atr, buf, width);
char fillbuf[256];
if(width > len) {
memset(fillbuf, fillchar, width-len);
fillbuf[width-len] = NUL;
}
else {
*fillbuf = NUL;
}
gvid_printf("\033[%u;%uH%s%*.*s%s", row+1, col+1, color,
min_len, min_len, buf, fillbuf
);
#endif
}
// ------------------------------------------------------------------
// Print horizontal line of character and attribute
2001-04-15 19:24:44 +00:00
#if (defined(__MSDOS__) || defined(__UNIX__)) && !defined(__USE_NCURSES__)
2000-02-25 10:15:17 +00:00
void _vputx(int row, int col, int atr, char chr, uint len) {
gdma p = gdmaptr(col, row);
word tmp = vcatch(chr, atr);
2000-02-25 10:15:17 +00:00
_farsetsel(_dos_ds);
for(uint n=0; n<len; n++) {
_farnspokew(p, tmp);
p += ATTRSIZE;
}
}
#endif
// ------------------------------------------------------------------
// Print horizontal line of character and attribute
void vputx(int row, int col, int atr, vchar chr, uint len) {
#if defined(__USE_NCURSES__)
mvhline(row, col, vcatch(gvid_tcpr(chr), atr), len);
2000-02-25 10:15:17 +00:00
refresh();
#elif defined(__MSDOS__)
if(gvid->isdma()) {
_vputx(row, col, atr, chr, len);
}
else if(gvid->isbios() or gvid->iscga()) {
i86 cpu;
cpu.ah(2);
cpu.bh(0);
cpu.dh((byte)row);
cpu.dl((byte)col);
cpu.genint(0x10);
cpu.ah(9);
cpu.al(chr);
cpu.bh(0);
cpu.bl((byte)atr);
cpu.cx((word)len);
cpu.genint(0x10);
}
#elif defined(__OS2__)
vatch filler = vcatch(chr, atr);
VioWrtNCell((BYTE *)&filler, (USHORT)len, (USHORT)row, (USHORT)col, 0);
2000-02-25 10:15:17 +00:00
#elif defined(__WIN32__)
vatch filler = vcatch(chr, atr);
for(int i = 0; i < len; i++)
gvid->bufwrd[i] = filler;
vputws(row, col, gvid->bufwrd, len);
2000-02-25 10:15:17 +00:00
#elif defined(__UNIX__)
char buf[256];
char* color = gvid_newattr(atr);
gvid_cvtchr(chr);
_vputx(row, col, atr, chr, len);
memset(buf, chr, len);
buf[len] = NUL;
gvid_printf("\033[%u;%uH%s%s", row+1, col+1, color, buf);
#endif
}
// ------------------------------------------------------------------
// Print vertical line of character and attribute
2001-04-15 19:24:44 +00:00
#if (defined(__MSDOS__) || defined(__UNIX__)) && !defined(__USE_NCURSES__)
2000-02-25 10:15:17 +00:00
inline void _vputy(int row, int col, int atr, char chr, uint len) {
gdma p = gdmaptr(col, row);
word tmp = vcatch(chr, atr);
2000-02-25 10:15:17 +00:00
_farsetsel(_dos_ds);
for(uint n=0; n<len; n++) {
_farnspokew(p, tmp);
p += ATTRSIZE*gvid->numcols;
}
}
#endif
// ------------------------------------------------------------------
// Print vertical line of character and attribute
void vputy(int row, int col, int atr, vchar chr, uint len) {
#if defined(__USE_NCURSES__)
mvvline(row, col, vcatch(gvid_tcpr(chr), atr), len);
2000-02-25 10:15:17 +00:00
refresh();
#elif defined(__MSDOS__)
if(gvid->isdma()) {
_vputy(row, col, atr, chr, len);
}
else if(gvid->isbios() or gvid->iscga()) {
for(uint n=0; n<len; n++) {
i86 cpu;
cpu.ah(2);
cpu.bh(0);
cpu.dh((byte)row++);
cpu.dl((byte)col);
cpu.genint(0x10);
cpu.ah(9);
cpu.al(chr);
cpu.bh(0);
cpu.bl((byte)atr);
cpu.cx(1);
cpu.genint(0x10);
}
}
#elif defined(__OS2__)
vatch filler = vcatch(chr, atr);
2000-02-25 10:15:17 +00:00
for(int n=0; n<len; n++)
VioWrtNCell((BYTE *)&filler, 1, (USHORT)row++, (USHORT)col, 0);
2000-02-25 10:15:17 +00:00
#elif defined(__WIN32__)
vatch filler = vcatch(chr, atr);
for(int i=0; i < len; i++)
vputw(row++, col, filler);
2000-02-25 10:15:17 +00:00
#elif defined(__UNIX__)
char* color = gvid_newattr(atr);
gvid_cvtchr(chr);
_vputy(row, col, atr, chr, len);
char buf[2048];
sprintf(buf, "\033[%u;%uH%s", row+1, col+1, color);
char* p = buf + strlen(buf);
for(uint n=0; n<(len-1); n++) {
*p++ = chr;
if(col == gvid->numcols-1) {
sprintf(p, "\033[%u;%uH", row+n+2, col+1);
p += strlen(p);
}
else {
strcpy(p, "\033[D\033[B");
p += 6;
}
}
*p++ = chr;
*p = NUL;
gvid_printf("%s", buf);
#endif
}
// ------------------------------------------------------------------
// Get character and attribute at cursor position
2001-04-15 19:24:44 +00:00
#if (defined(__MSDOS__) || defined(__UNIX__)) && !defined(__USE_NCURSES__)
2000-02-25 10:15:17 +00:00
inline word _vgetw(int row, int col) {
return _farpeekw(_dos_ds, gdmaptr(col, row));
}
#endif
// ------------------------------------------------------------------
// Get character and attribute at cursor position
vatch vgetw(int row, int col) {
#if defined(__USE_NCURSES__)
return mvinch(row, col);
#elif defined(__MSDOS__)
if(gvid->isdma()) {
return _vgetw(row, col);
}
else if(gvid->isbios() or gvid->iscga()) {
i86 cpu;
cpu.ah(2);
cpu.bh(0);
cpu.dh((byte)row);
cpu.dl((byte)col);
cpu.genint(0x10);
cpu.ah(8);
cpu.bh(0);
cpu.genint(0x10);
return cpu.ax();
}
return 0;
#elif defined(__OS2__)
vatch chat;
USHORT len=sizeof(chat);
2000-02-25 10:15:17 +00:00
VioReadCellStr((BYTE *)&chat, &len, (USHORT)row, (USHORT)col, 0);
2000-02-25 10:15:17 +00:00
return chat;
#elif defined(__WIN32__)
vatch chat;
const COORD coord = {0, 0};
const COORD size = {1, 1};
SMALL_RECT rect;
2000-02-25 10:15:17 +00:00
rect.Top = row;
rect.Left = col;
rect.Bottom = row+size.Y-1;
rect.Right = col+size.X-1;
ReadConsoleOutput(gvid_hout, &chat, size, coord, &rect);
2000-02-25 10:15:17 +00:00
return chat;
2000-02-25 10:15:17 +00:00
#elif defined(__UNIX__)
return _vgetw(row, col);
#endif
}
// ------------------------------------------------------------------
// Get character and attribute at cursor position
void vgetc(int row, int col, int* atr, vchar* chr) {
2001-04-15 19:24:44 +00:00
if((row < 0) or (row > gvid->numrows-1) or (col < 0) or (col > gvid->numcols-1)) {
2001-03-03 13:16:14 +00:00
*chr = ' ';
*atr = 0;
}
else {
vatch tmp = vgetw(row, col);
2000-02-25 10:15:17 +00:00
2001-03-03 13:16:14 +00:00
*chr = vgchar(tmp);
*atr = vgattr(tmp);
}
2000-02-25 10:15:17 +00:00
}
// ------------------------------------------------------------------
// Scroll screen area
2001-04-15 19:24:44 +00:00
#if (defined(__MSDOS__) || defined(__UNIX__)) && !defined(__USE_NCURSES__)
2000-02-25 10:15:17 +00:00
static void _vscroll(int srow, int scol, int erow, int ecol, int atr, int lines) {
word empty = (atr << 8) | ' ';
if(lines > 0) {
while(lines--) {
int nrow = srow;
int l = ((ecol - scol) + 1);
gdma scrptr = gdmaptr(scol, srow);
while(nrow++ < erow) {
gdmacpy(_dos_ds, (gdma)scrptr, _dos_ds, (gdma)(scrptr+ATTRSIZE*gvid->numcols), l*sizeof(word));
scrptr += ATTRSIZE*gvid->numcols;
}
_farsetsel(_dos_ds);
for(l *= ATTRSIZE; l>0;) {
l -= ATTRSIZE;
_farnspokew(scrptr+l, empty);
}
}
}
else {
while(lines++) {
int nrow = erow;
int l = ((ecol - scol) + 1);
gdma scrptr = gdmaptr(scol, erow);
while(nrow-- >= (srow + 1)) {
gdmacpy(_dos_ds, (gdma)scrptr, _dos_ds, (gdma)(scrptr-ATTRSIZE*gvid->numcols), l*sizeof(word));
scrptr -= ATTRSIZE*gvid->numcols;
}
_farsetsel(_dos_ds);
for(l *= ATTRSIZE; l>0;) {
l -= ATTRSIZE;
_farnspokew(scrptr+l, empty);
}
}
}
}
#endif
// ------------------------------------------------------------------
// Scroll screen area
void vscroll(int srow, int scol, int erow, int ecol, int atr, int lines) {
#if defined(__USE_NCURSES__)
vatch filler = vcatch(' ', atr);
2000-02-25 10:15:17 +00:00
// Currently implemented with vsave/vrestore
// Does anyone know a better solution?
if(lines >= 0) {
if(lines <= 1 + erow - srow) {
vsavebuf *buf = vsave(srow + lines, scol, erow, ecol);
vrestore(buf, srow, scol, erow - lines, ecol);
throw_xfree(buf);
2000-02-25 10:15:17 +00:00
}
else
lines = 1 + erow - srow;
for(int counter = 0; counter < lines; counter++)
mvhline(1 + erow + counter - lines, scol, filler, 1 + ecol - scol);
2000-02-25 10:15:17 +00:00
refresh();
}
else {
lines*=-1;
if(lines <= 1 + erow - srow) {
vsavebuf *buf = vsave(srow, scol, erow - lines, ecol);
vrestore(buf, srow + lines, scol, erow, ecol);
throw_xfree(buf);
2000-02-25 10:15:17 +00:00
}
else
lines = 1 + erow - srow;
for(int counter = 0; counter < lines; counter++)
mvhline(srow + counter, scol, filler, 1 + ecol - scol);
2000-02-25 10:15:17 +00:00
refresh();
}
#elif defined(__MSDOS__)
if(gvid->isdma()) {
_vscroll(srow, scol, erow, ecol, atr, lines);
}
else if(gvid->isbios() or gvid->iscga()) {
i86 cpu;
cpu.ah((byte)(lines > 0 ? 6 : 7));
cpu.al((byte)absolute(lines));
cpu.bh((byte)atr);
cpu.ch((byte)srow);
cpu.cl((byte)scol);
cpu.dh((byte)erow);
cpu.dl((byte)ecol);
cpu.genint(0x10);
}
#elif defined(__OS2__)
vatch filler = vcatch(' ', atr);
2000-02-25 10:15:17 +00:00
if(lines > 0)
VioScrollUp((USHORT)srow, (USHORT)scol, (USHORT)erow, (USHORT)ecol, (USHORT)lines, (BYTE *)&filler, 0);
2000-02-25 10:15:17 +00:00
else
VioScrollDn((USHORT)srow, (USHORT)scol, (USHORT)erow, (USHORT)ecol, (USHORT)-lines, (BYTE *)&filler, 0);
2000-02-25 10:15:17 +00:00
#elif defined(__WIN32__)
SMALL_RECT r;
COORD c = {scol, srow - lines};
vatch filler = vcatch(' ', atr);
2000-02-25 10:15:17 +00:00
r.Left = (SHORT)scol;
r.Top = (SHORT)srow;
r.Right = (SHORT)ecol;
r.Bottom = (SHORT)erow;
ScrollConsoleScreenBuffer(gvid_hout, &r, &r, c, &filler);
2000-02-25 10:15:17 +00:00
#elif defined(__UNIX__)
_vscroll(srow, scol, erow, ecol, atr, lines);
gdma ptr = gdmaptr(scol, srow);
int len = ecol-scol+1;
for(int nrow=srow; nrow<=erow; nrow++) {
vputansi(nrow, scol, ptr, len);
ptr += ATTRSIZE*gvid->numcols;
}
#endif
}
// ------------------------------------------------------------------
// Returns true if cursor invisible
bool vcurhidden() {
return __vcurhidden;
}
// ------------------------------------------------------------------
// Get cursor position
void vposget(int* row, int* col) {
#if defined(__USE_NCURSES__)
getyx(stdscr, gvid->currow, gvid->curcol);
#elif defined(__MSDOS__)
i86 cpu;
cpu.ah(3);
cpu.bh(0);
cpu.genint(0x10);
gvid->currow = cpu.dh();
gvid->curcol = cpu.dl();
#elif defined(__OS2__)
USHORT _getrow, _getcol;
VioGetCurPos(&_getrow, &_getcol, 0);
gvid->currow = _getrow;
gvid->curcol = _getcol;
#elif defined(__WIN32__)
CONSOLE_SCREEN_BUFFER_INFO i;
GetConsoleScreenBufferInfo(gvid_hout, &i);
gvid->currow = i.dwCursorPosition.Y;
gvid->curcol = i.dwCursorPosition.X;
#elif defined(__UNIX__)
// Not available
#endif
*row = gvid->currow;
*col = gvid->curcol;
}
// ------------------------------------------------------------------
// Set cursor position
void vposset(int row, int col) {
gvid->currow = row;
gvid->curcol = col;
#if defined(__USE_NCURSES__)
move(row, col);
refresh();
#elif defined(__MSDOS__)
i86 cpu;
cpu.ah(2);
cpu.bh(0);
cpu.dh((byte)row);
cpu.dl((byte)col);
cpu.genint(0x10);
#elif defined(__OS2__)
VioSetCurPos((USHORT)row, (USHORT)col, 0);
#elif defined(__WIN32__)
// No need to set the cursor position if its not visible
// Strangely, this is a major speedup to screen-output
2000-02-25 10:15:17 +00:00
if(__vcurhidden)
return;
2000-02-25 10:15:17 +00:00
COORD c = {col, row};
2000-02-25 10:15:17 +00:00
SetConsoleCursorPosition(gvid_hout, c);
#elif defined(__UNIX__)
gvid_printf("\x1B[%u;%uH", row+1, col+1);
#endif
}
// ------------------------------------------------------------------
// Clears the screen and homes the cursor
void vclrscr() {
vclrscr(vgattr(vgetw(gvid->currow, gvid->curcol)));
2000-02-25 10:15:17 +00:00
}
// ------------------------------------------------------------------
// Clears the screen using given attribute and homes the cursor
2001-04-15 19:24:44 +00:00
#if (defined(__MSDOS__) || defined(__UNIX__)) && !defined(__USE_NCURSES__)
2000-02-25 10:15:17 +00:00
static void _vclrscr(int atr) {
int len = gvid->numrows * gvid->numcols;
_vputx(0, 0, atr, ' ', len);
}
#endif
// ------------------------------------------------------------------
// Clears the screen using given attribute and homes the cursor
void vclrscr(int atr) {
#if defined(__USE_NCURSES__)
clearok(stdscr, TRUE);
vatch filler = vcatch(' ', atr);
2000-02-25 10:15:17 +00:00
for(int row = 0; row < LINES; row++)
mvhline(row, 0, filler, COLS);
2000-02-25 10:15:17 +00:00
move(0, 0);
refresh();
#elif defined(__MSDOS__)
if(gvid->isdma()) {
_vclrscr(atr);
}
else if(gvid->isbios() or gvid->iscga()) {
i86 cpu;
cpu.ax(0x0600); // clear screen by scrolling it
cpu.bh((byte)atr);
cpu.cx(0);
cpu.dh((byte)(gvid->numrows - 1));
cpu.dl((byte)(gvid->numcols - 1));
cpu.genint(0x10);
}
#elif defined(__OS2__)
vatch filler = vcatch(' ', atr);
VioScrollUp(0, 0, 0xFFFF, 0xFFFF, 0xFFFF, (BYTE *)&filler, 0);
2000-02-25 10:15:17 +00:00
#elif defined(__WIN32__)
COORD c = {0, 0};
2000-02-25 10:15:17 +00:00
DWORD wr, len = gvid->numrows * gvid->numcols;
// Filling with space seems to work for both Unicode and regular functions
2000-02-25 10:15:17 +00:00
FillConsoleOutputCharacter(gvid_hout, ' ', len, c, &wr);
FillConsoleOutputAttribute(gvid_hout, (WORD)atr, len, c, &wr);
#elif defined(__UNIX__)
_vclrscr(atr);
gvid_printf("%s\x1B[2J", gvid_newattr(atr));
#endif
vposset(0,0);
}
// ------------------------------------------------------------------
// Saves the current screen and returns pointer to buffer
2001-04-15 19:24:44 +00:00
#if (defined(__MSDOS__) || defined(__UNIX__)) && !defined(__USE_NCURSES__)
2000-02-25 10:15:17 +00:00
static void _vsave(word* buf, int len1, int srow, int scol, int erow) {
const int len2 = len1*sizeof(word);
gdma p = gdmaptr(scol, srow);
for(int nrow=srow; nrow<=erow; nrow++) {
gdmacpy(_my_ds(), (gdma)buf, _dos_ds, (gdma)p, len2);
p += ATTRSIZE*gvid->numcols;
buf += len1;
}
}
#endif
// ------------------------------------------------------------------
// Saves the current screen and returns pointer to buffer
vsavebuf* vsave(int srow, int scol, int erow, int ecol) {
2000-02-25 10:15:17 +00:00
if(srow == -1) srow = 0;
if(scol == -1) scol = 0;
if(erow == -1) erow = gvid->numrows-1;
if(ecol == -1) ecol = gvid->numcols-1;
2000-02-25 10:15:17 +00:00
vsavebuf* sbuf = (vsavebuf*)throw_xmalloc(sizeof(vsavebuf) + (erow - srow + 1) * (ecol - scol + 1) * sizeof(vatch));
2000-02-25 10:15:17 +00:00
if(sbuf) {
vatch* buf = sbuf->data;
2000-02-25 10:15:17 +00:00
sbuf->top = srow;
sbuf->left = scol;
sbuf->bottom = erow;
sbuf->right = ecol;
2000-02-25 10:15:17 +00:00
#if defined(__USE_NCURSES__)
for(int row=srow; row<=erow; row++)
for(int col=scol; col<=ecol; col++)
*buf++ = mvinch(row, col);
#elif defined(__MSDOS__)
int len1 = ecol-scol+1;
if(gvid->isdma()) {
_vsave(buf, len1, srow, scol, erow);
}
else if(gvid->isbios() or gvid->iscga()) {
i86 cpu;
byte* p = (byte*)buf;
for(byte row=(byte)srow; row<=erow; row++) {
for(byte col=(byte)scol; col<=ecol; col++) {
cpu.ah(2);
cpu.bh(0);
cpu.dh(row);
cpu.dl(col);
cpu.genint(0x10);
cpu.ah(8);
cpu.bh(0);
cpu.genint(0x10);
*p++ = cpu.al();
*p++ = cpu.ah();
}
}
}
#elif defined(__OS2__)
int len1 = (int)(ecol-scol+1);
2000-02-25 10:15:17 +00:00
#if defined(__BORLANDC__)
PCHAR16 ptr = (PCHAR16)buf;
#else
PCH ptr = (PCH)buf;
#endif
USHORT len2 = (USHORT)(len1*sizeof(word));
for(int nrow=srow; nrow<=erow; nrow++) {
2000-02-25 10:15:17 +00:00
VioReadCellStr(ptr, &len2, nrow, scol, 0);
ptr += len2;
}
#elif defined(__WIN32__)
const COORD coord = {0, 0};
COORD size = {ecol-scol+1, erow-srow+1};
SMALL_RECT r;
2000-02-25 10:15:17 +00:00
// Set the source rectangle.
r.Top = srow;
r.Left = scol;
r.Bottom = erow;
r.Right = ecol;
2000-02-25 10:15:17 +00:00
if(WinVer.dwPlatformId == VER_PLATFORM_WIN32_NT)
ReadConsoleOutputW(gvid_hout, buf, size, coord, &r);
else
ReadConsoleOutputA(gvid_hout, buf, size, coord, &r);
2000-02-25 10:15:17 +00:00
#elif defined(__UNIX__)
int len1 = ecol-scol+1;
_vsave(buf, len1, srow, scol, erow);
#endif
}
return sbuf;
}
// ------------------------------------------------------------------
// Redraws a previously saved screen
2001-04-15 19:24:44 +00:00
#if (defined(__MSDOS__) || defined(__UNIX__)) && !defined(__USE_NCURSES__)
2000-02-25 10:15:17 +00:00
static void _vredraw(word* buf, int len1, int srow, int scol, int erow) {
const int len2 = len1*sizeof(word);
gdma p = gdmaptr(scol, srow);
for(int nrow=srow; nrow<=erow; nrow++) {
gdmacpy(_dos_ds, (gdma)p, _my_ds(), (gdma)buf, len2);
p += ATTRSIZE*gvid->numcols;
buf += len1;
}
}
#endif
// ------------------------------------------------------------------
// Redraws a previously saved screen
void vrestore(vsavebuf* sbuf, int srow, int scol, int erow, int ecol) {
2000-02-25 10:15:17 +00:00
if(srow != -1) sbuf->top = srow;
if(scol != -1) sbuf->left = scol;
if(erow != -1) sbuf->bottom = erow;
if(ecol != -1) sbuf->right = ecol;
2000-02-25 10:15:17 +00:00
srow = sbuf->top;
scol = sbuf->left;
erow = sbuf->bottom;
ecol = sbuf->right;
vatch *buf = sbuf->data;
2000-02-25 10:15:17 +00:00
#if defined(__USE_NCURSES__)
2000-02-25 10:15:17 +00:00
for(int row=srow; row<=erow; row++)
for(int col=scol; col<=ecol; col++)
mvaddch(row, col, *buf++);
2000-02-25 10:15:17 +00:00
refresh();
2000-02-25 10:15:17 +00:00
#elif defined(__MSDOS__)
int len1 = ecol-scol+1;
if(gvid->isdma()) {
_vredraw(buf, len1, srow, scol, erow);
}
else if(gvid->isbios() or gvid->iscga()) {
i86 cpu;
byte* p = (byte*)buf;
for(byte row=(byte)srow; row<=erow; row++) {
for(byte col=(byte)scol; col<=ecol; col++) {
cpu.ah(2);
cpu.bh(0);
cpu.dh(row);
cpu.dl(col);
cpu.genint(0x10);
cpu.ah(9);
cpu.al(*p++);
cpu.bh(0);
cpu.bl(*p++);
cpu.cx(1);
cpu.genint(0x10);
}
}
}
#elif defined(__OS2__)
USHORT len1 = (USHORT)(ecol-scol+1);
USHORT len2 = (USHORT)(len1*sizeof(word));
#if defined(__BORLANDC__)
PCHAR16 ptr = (PCHAR16)buf;
#else
PCH ptr = (PCH)buf;
#endif
for(USHORT nrow=srow; nrow<=erow; nrow++) {
VioWrtCellStr(ptr, len2, nrow, scol, 0);
ptr += len2;
}
#elif defined(__WIN32__)
const COORD coord = {0, 0};
COORD size = {ecol-scol+1, erow-srow+1};
SMALL_RECT r;
2000-02-25 10:15:17 +00:00
// Set the source rectangle.
r.Top = srow;
r.Left = scol;
r.Bottom = erow;
r.Right = ecol;
2000-02-25 10:15:17 +00:00
if(WinVer.dwPlatformId == VER_PLATFORM_WIN32_NT)
WriteConsoleOutputW(gvid_hout, buf, size, coord, &r);
else
WriteConsoleOutputA(gvid_hout, buf, size, coord, &r);
2000-02-25 10:15:17 +00:00
#elif defined(__UNIX__)
int len1 = ecol-scol+1;
_vredraw(buf, len1, srow, scol, erow);
int atr = vgattr(*buf);
2000-02-25 10:15:17 +00:00
char* color = gvid_newattr(atr);
gvid_printf("%s", color);
for(int nrow=srow; nrow<=erow; nrow++) {
vputansi(nrow, scol, buf, len1);
buf += len1;
}
#endif
}
// ------------------------------------------------------------------
// Sets the cursor shape/size
void vcurset(int sline, int eline) {
if(eline) {
gvid->curr.cursor.start = sline;
gvid->curr.cursor.end = eline;
__vcurhidden = false;
}
#if defined(__USE_NCURSES__)
if((sline == 0) and (eline == 0))
curs_set(0);
else if((eline - sline) <= 4)
2000-02-25 10:15:17 +00:00
curs_set(1);
else
curs_set(2);
#elif defined(__MSDOS__)
if(eline == 0) {
int _dvhide = __gdvdetected ? 0x01 : 0x30;
sline = ((gvid->adapter>=V_HGC) and (gvid->adapter<=V_INCOLOR)) ? 0x3F : _dvhide;
}
i86 cpu;
cpu.ah(1);
cpu.ch((byte)sline);
cpu.cl((byte)eline);
cpu.genint(0x10);
#elif defined(__OS2__)
VIOCURSORINFO vioci;
VioGetCurType(&vioci, 0);
vioci.yStart = (USHORT)sline;
vioci.cEnd = (USHORT)eline;
vioci.attr = (USHORT)((eline == 0) ? 0xFFFF : gvid->curr.color.textattr);
VioSetCurType(&vioci, 0);
#elif defined(__WIN32__)
CONSOLE_CURSOR_INFO cci;
if(eline)
vposset(gvid->currow, gvid->curcol);
else /* Move cursor to bottom right corner (workaround of the win9x console bug) */
vposset(gvid->numrows-1, gvid->numcols-1);
2000-02-25 10:15:17 +00:00
cci.dwSize = (eline and sline) ? sline : 100;
cci.bVisible = eline ? true : false;
SetConsoleCursorInfo(gvid_hout, &cci);
#elif defined(__UNIX__)
gvid_printf("\033[?25%c", eline ? 'h' : 'l');
#endif
}
// ------------------------------------------------------------------
// Hides the cursor
void vcurhide() {
if(not __vcurhidden) {
#if defined(__USE_NCURSES__)
curs_set(0);
#else
vcurset(0,0);
#endif
__vcurhidden = true;
}
}
// ------------------------------------------------------------------
// Reveals the cursor
void vcurshow() {
if(__vcurhidden) {
vcurset(gvid->curr.cursor.start, gvid->curr.cursor.end);
__vcurhidden = false;
}
}
// ------------------------------------------------------------------
// Sets a large cursor
void vcurlarge() {
#if defined(__USE_NCURSES__)
curs_set(2);
#else
vcurshow();
#if defined(__MSDOS__)
switch(gvid->adapter) {
case V_CGA:
vcurset(1,7);
break;
case V_EGA:
if(gvid->numrows == 25) {
vcurset(1,7);
}
else {
word* p = (word*)0x0463; // video BIOS data area
outpw(*p,0x000A); // update cursor start register
outpw(*p,0x0A0B); // update cursor end register
}
break;
case V_VGA:
vcurset(1,7);
break;
default: // one of the monochrome cards
vcurset(1,12);
}
#elif defined(__OS2__)
vcurset(1, gvid->curr.screen.cheight-1);
#elif defined(__WIN32__)
vcurset(90, true);
#endif
#endif
}
// ------------------------------------------------------------------
// Sets a small cursor
void vcursmall() {
#if defined(__USE_NCURSES__)
curs_set(1);
#else
vcurshow();
#if defined(__MSDOS__)
switch(gvid->adapter) {
case V_CGA:
vcurset(6,7);
break;
case V_EGA:
if(gvid->numrows == 25) {
vcurset(6,7);
}
else {
word* p = (word*)0x0463; // video BIOS data area
outpw(*p,0x060A); // update cursor start register
outpw(*p,0x000B); // update cursor end register
}
break;
case V_VGA:
vcurset(6,7);
break;
default: // one of the monochrome cards
vcurset(11,12);
}
#elif defined(__OS2__)
vcurset(gvid->curr.screen.cheight-2, gvid->curr.screen.cheight-1);
#elif defined(__WIN32__)
vcurset(13, true);
#endif
#endif
}
// ------------------------------------------------------------------
// Table of characters used to display boxes
//
// Access box table characters via:
// _box_table(boxtype, x)
//
// where:
// boxtype is the number of the box type you want to use (0 - 5)
//
// x will be one of the following:
// 0 - upper left corner
// 1 - upper horizontal line
// 2 - upper right corner
// 3 - left vertical line
// 4 - right vertical line
// 5 - lower left corner
// 6 - lower horizontal line
// 7 - lower right corner
// 8 - middle junction
// 9 - left vertical junction
// 10 - right vertical junction
// 11 - upper horizontal junction
// 12 - lower horizontal junction
// 13 - checkerboard
// 14 - solid block
// ------------------------------------------------------------------
2001-04-15 19:24:44 +00:00
#if !defined(__USE_NCURSES__)
2000-02-25 10:15:17 +00:00
char* __box_table[] = {
#if defined(__UNIX__) // This table will be actually patched at startup...
".-.||`-'+||-- #", // box type 0 Single border
".-.||`-'+||-- #", // box type 1 Double border
".-.||`-'+||-- #", // box type 2 Single top
".-.||`-'+||-- #", // box type 3 Double top
" #", // box type 4 With empty border
".-.||`-'+||-- #", // box type 5 No border at all
".-.||`-'+||-- #", // box type 6 Blocky border
".-.||`-'+||-- #", // box type 7 ASCII border
"lqkxxmqjntuwvaa", // box type 8 xterm single border
#else
"<EFBFBD>Ŀ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ô<EFBFBD><EFBFBD><EFBFBD><EFBFBD>", // box type 0 Single border
"<EFBFBD>ͻ<EFBFBD><EFBFBD><EFBFBD>ͼ<EFBFBD>̹<EFBFBD>ʰ<EFBFBD>", // box type 1 Double border
"<EFBFBD>ķ<EFBFBD><EFBFBD><EFBFBD>Ľ<EFBFBD>Ƕ<EFBFBD>а<EFBFBD>", // box type 2 Single top
"<EFBFBD>͸<EFBFBD><EFBFBD><EFBFBD>;<EFBFBD>Ƶ<EFBFBD>ϰ<EFBFBD>", // box type 3 Double top
" <20><>", // box type 4 With empty border
"<EFBFBD>Ŀ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ô<EFBFBD><EFBFBD><EFBFBD><EFBFBD>", // box type 5 No border at all
"<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݰ<EFBFBD>", // box type 6 Blocky border
".-.||`-'+||--##", // box type 7 ASCII border
"lqkxxmqjntuwvaa", // box type 8 xterm single border
#endif
};
#else
// ncurses ACS_nnn characters are usually computed at runtime, so
// we cannot use a static array
chtype _box_table(int type, int c) {
char asciiborder[] = ".-.||-'+||--##";
switch(type) {
case 4:
switch(c) {
case 13:
return ACS_BOARD;
case 14:
return ACS_BLOCK;
default:
return (chtype) ' ';
}
case 6:
switch(c) {
case 13:
return ACS_BOARD;
default:
return ACS_BLOCK;
}
case 7:
return (chtype) (asciiborder[c]);
default:
switch (c) {
case 0:
return ACS_ULCORNER;
case 1:
case 6:
return ACS_HLINE;
case 2:
return ACS_URCORNER;
case 3:
case 4:
return ACS_VLINE;
case 5:
return ACS_LLCORNER;
case 7:
return ACS_LRCORNER;
case 8:
return ACS_PLUS;
case 9:
return ACS_LTEE;
case 10:
return ACS_RTEE;
case 11:
return ACS_TTEE;
case 12:
return ACS_BTEE;
case 13:
return ACS_BOARD;
default:
return ACS_BLOCK;
}
}
}
#endif
// ------------------------------------------------------------------
2001-07-25 19:06:12 +00:00
#if defined(__UNIX__)
2000-02-25 10:15:17 +00:00
void gvid_boxcvt(char* s) {
2001-07-25 19:06:12 +00:00
while(*s)
*s++ = (char)gvid_boxcvtc(*s);
}
2000-02-25 10:15:17 +00:00
static uint32_t gvid_boxcvtc(char c) {
2001-07-25 19:06:12 +00:00
switch(c) {
#if 0
case '<EFBFBD>': return _box_table(8, 0);
case '<EFBFBD>': return _box_table(8, 1);
case '<EFBFBD>': return _box_table(8, 2);
case '<EFBFBD>': return _box_table(8, 4);
case '<EFBFBD>': return _box_table(8, 5);
case '<EFBFBD>': return _box_table(8, 7);
case '<EFBFBD>': return _box_table(8, 8);
case '<EFBFBD>': return _box_table(8, 9);
case '<EFBFBD>': return _box_table(8, 10);
case '<EFBFBD>': return _box_table(8, 11);
case '<EFBFBD>': return _box_table(8, 12);
#else
case '<EFBFBD>': return _box_table(0, 0);
case '<EFBFBD>': return _box_table(0, 1);
case '<EFBFBD>': return _box_table(0, 2);
case '<EFBFBD>': return _box_table(0, 4);
case '<EFBFBD>': return _box_table(0, 5);
case '<EFBFBD>': return _box_table(0, 7);
case '<EFBFBD>': return _box_table(0, 8);
case '<EFBFBD>': return _box_table(0, 9);
case '<EFBFBD>': return _box_table(0, 10);
case '<EFBFBD>': return _box_table(0, 11);
case '<EFBFBD>': return _box_table(0, 12);
case '<EFBFBD>': return _box_table(1, 0);
case '<EFBFBD>': return _box_table(1, 1);
case '<EFBFBD>': return _box_table(1, 2);
case '<EFBFBD>': return _box_table(1, 4);
case '<EFBFBD>': return _box_table(1, 5);
case '<EFBFBD>': return _box_table(1, 7);
case '<EFBFBD>': return _box_table(1, 8);
case '<EFBFBD>': return _box_table(1, 9);
case '<EFBFBD>': return _box_table(1, 10);
case '<EFBFBD>': return _box_table(1, 11);
case '<EFBFBD>': return _box_table(1, 12);
#endif
2000-02-25 10:15:17 +00:00
}
2001-07-25 19:06:12 +00:00
return c;
2000-02-25 10:15:17 +00:00
}
#endif
// ------------------------------------------------------------------
// Draws a text box on the screen
void vbox(int srow, int scol, int erow, int ecol, int box, int hiattr, int loattr) {
if(loattr == -1)
loattr = hiattr;
else if(loattr == -2)
loattr = (int)((hiattr & 0x08) ? (hiattr & 0xF7) : (hiattr | 0x08));
#if defined(__UNIX__)
hiattr |= ACSET;
loattr |= ACSET;
#endif
vputc(srow, scol, hiattr, _box_table(box, 0)); // Top left corner
vputx(srow, scol+1, hiattr, _box_table(box, 1), ecol-scol-1); // Top border
vputc(srow, ecol, loattr, _box_table(box, 2)); // Top right corner
vputy(srow+1, scol, hiattr, _box_table(box, 3), erow-srow-1); // Left border
vputy(srow+1, ecol, loattr, _box_table(box, 4), erow-srow-1); // Right border
vputc(erow, scol, hiattr, _box_table(box, 5)); // Bottom left corner
vputx(erow, scol+1, loattr, _box_table(box, 6), ecol-scol-1); // Bottom border
vputc(erow, ecol, loattr, _box_table(box, 7)); // Bottom right corner
}
// ------------------------------------------------------------------
// Fills an area of screen with a character & attribute
void vfill(int srow, int scol, int erow, int ecol, vchar chr, int atr) {
int width = ecol-scol+1;
for(int crow=srow; crow<=erow; crow++)
vputx(crow, scol, atr, chr, width);
}
// ------------------------------------------------------------------