// 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 #include #include #include #include #include #include #if defined(__OS2__) #define INCL_BASE #include #ifndef __EMX__ #define PCCH CHAR* #endif #endif #ifdef __WIN32__ #include #endif #ifdef __GNUC__ #include #endif #if defined(__DJGPP__) #include #endif // ------------------------------------------------------------------ // Check if Borland C++ for OS/2 1.0 header has been fixed #if defined(__OS2__) and 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 // ------------------------------------------------------------------ static bool __vcurhidden = false; #if not defined(__USE_NCURSES__) // ------------------------------------------------------------------ #ifdef __WIN32__ extern HANDLE gvid_hout; #endif // ------------------------------------------------------------------ #if defined(__MSDOS__) or defined(__UNIX__) #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 bool gvid_xterm; 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>>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; nbufansi); } // ------------------------------------------------------------------ #endif #endif // not defined(__USE_NCURSES__) // ------------------------------------------------------------------ extern int __gdvdetected; // ------------------------------------------------------------------ // 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)); } #if not defined(__USE_NCURSES__) // ------------------------------------------------------------------ #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) { // 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) { 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) { 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, ACS_LARROW, (chtype) ACS_RARROW, (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 }; 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 #if (defined(__MSDOS__) or defined(__UNIX__)) and not defined(__USE_NCURSES__) 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((byte)(chat&0xFF)); cpu.bh(0); cpu.bl((byte)(chat>>8)); cpu.cx(1); cpu.genint(0x10); } #elif defined(__OS2__) BYTE tmp[2]; tmp[0] = (BYTE)(chat & 0xFF); tmp[1] = (BYTE)(chat >> 8); VioWrtNCell(tmp, 1, (USHORT)row, (USHORT)col, 0); #elif defined(__WIN32__) COORD coord; DWORD x; word atr = (word) (chat >> 8); coord.X = (SHORT) col; coord.Y = (SHORT) row; WriteConsoleOutputAttribute(gvid_hout, &atr, 1, coord, &x); WriteConsoleOutputCharacter(gvid_hout, (char* ) &chat, 1, coord, &x); #elif defined(__UNIX__) char chr = (char)(chat & 0xFF); int atr = chat >> 8; char* color = gvid_newattr(atr); chat = (word)(chr | (atr << 8)); 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; nbufwrd; char* c = gvid->bufchr; for(int i = 0; i < len; i++) { *c++ = *p++; *q++ = *p++; } WriteConsoleOutputAttribute(gvid_hout, gvid->bufwrd, len, coord, &x); WriteConsoleOutputCharacter(gvid_hout, gvid->bufchr, len, coord, &x); #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, gvid_tcpr(chr) | gvid_attrcalc(atr)); refresh(); #elif defined(__MSDOS__) if(gvid->isdma()) { _vputw(row, col, (word)((atr << 8) | chr)); } 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); } #elif defined(__OS2__) BYTE tmp[2]; tmp[0] = chr; tmp[1] = (BYTE)atr; VioWrtNCell(tmp, 1, (USHORT)row, (USHORT)col, 0); #elif defined(__WIN32__) COORD coord; DWORD x; coord.X = (SHORT) col; coord.Y = (SHORT) row; WriteConsoleOutputAttribute(gvid_hout, (word *) &atr, 1, coord, &x); WriteConsoleOutputCharacter(gvid_hout, (char *) &chr, 1, coord, &x); #elif defined(__UNIX__) char* color = gvid_newattr(atr); gvid_cvtstr(&chr, 1); _vputw(row, col, (word)((atr << 8) | chr)); 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 vputs(row, col, atr, str); #endif } // ------------------------------------------------------------------ // Print string with attribute at specfied location 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, (atr << 8) | *str++); 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__) COORD coord; DWORD x; int len = strlen(str); coord.X = (SHORT) col; coord.Y = (SHORT) row; FillConsoleOutputAttribute(gvid_hout, (word) atr, len, coord, &x); WriteConsoleOutputCharacter(gvid_hout, str, len, coord, &x); #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, (atr << 8) | *str++); p += ATTRSIZE; } gvid_printf("\033[%u;%uH%s%s", row+1, col+1, color, buf); #endif } // ------------------------------------------------------------------ // Print string with attribute at specfied location #if (defined(__MSDOS__) or defined(__UNIX__)) and not defined(__USE_NCURSES__) 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(counterisdma()) { _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) { BYTE tmp[2]; tmp[0] = fillchar; tmp[1] = (BYTE)atr; VioWrtNCell(tmp, (USHORT)(width-len), (USHORT)row, (USHORT)(col+len), 0); } #elif defined(__WIN32__) COORD coord; DWORD x; int len = minimum_of_two(strlen(str), width); coord.X = (SHORT) col; coord.Y = (SHORT) row; FillConsoleOutputAttribute(gvid_hout, (word) atr, width, coord, &x); WriteConsoleOutputCharacter(gvid_hout, str, len, coord, &x); if(width > len) { coord.X += (SHORT) len; len = width - len; FillConsoleOutputCharacter(gvid_hout, fillchar, len, coord, &x); } #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 #if (defined(__MSDOS__) or defined(__UNIX__)) and not defined(__USE_NCURSES__) void _vputx(int row, int col, int atr, char chr, uint len) { gdma p = gdmaptr(col, row); word tmp = (word)((atr << 8) | chr); _farsetsel(_dos_ds); for(uint n=0; nisdma()) { _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__) BYTE tmp[2]; tmp[0] = chr; tmp[1] = (BYTE)atr; VioWrtNCell(tmp, (USHORT)len, (USHORT)row, (USHORT)col, 0); #elif defined(__WIN32__) COORD c; c.X = (SHORT)col; c.Y = (SHORT)row; DWORD wr; FillConsoleOutputCharacter(gvid_hout, chr, len, c, &wr); FillConsoleOutputAttribute(gvid_hout, (WORD)atr, len, c, &wr); #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 #if (defined(__MSDOS__) or defined(__UNIX__)) and not defined(__USE_NCURSES__) inline void _vputy(int row, int col, int atr, char chr, uint len) { gdma p = gdmaptr(col, row); word tmp = (word)((atr<<8) | chr); _farsetsel(_dos_ds); for(uint n=0; nnumcols; } } #endif // ------------------------------------------------------------------ // Print vertical line of character and attribute void vputy(int row, int col, int atr, vchar chr, uint len) { #if defined(__USE_NCURSES__) int attr = gvid_attrcalc(atr); mvvline(row, col, gvid_tcpr(chr) | attr, len); refresh(); #elif defined(__MSDOS__) if(gvid->isdma()) { _vputy(row, col, atr, chr, len); } else if(gvid->isbios() or gvid->iscga()) { for(uint n=0; nnumcols-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 #if (defined(__MSDOS__) or defined(__UNIX__)) and not defined(__USE_NCURSES__) 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__) word chat; USHORT _row=(USHORT)row, _col=(USHORT)col, len=sizeof(chat); #if defined(__EMX__) VioReadCellStr((PCH)&chat, &len, _row, _col, 0); #else VioReadCellStr((CHAR*)&chat, &len, _row, _col, 0); #endif return chat; #elif defined(__WIN32__) COORD coord; DWORD x; word atr; char chr; coord.X = (SHORT) col; coord.Y = (SHORT) row; ReadConsoleOutputAttribute(gvid_hout, &atr, 1, coord, &x); ReadConsoleOutputCharacter(gvid_hout, &chr, 1, coord, &x); return (word)((atr << 8) | chr); #elif defined(__UNIX__) return _vgetw(row, col); #endif } // ------------------------------------------------------------------ // Get character and attribute at cursor position #if (defined(__MSDOS__) or defined(__UNIX__)) and not defined(__USE_NCURSES__) inline void _vgetc(int row, int col, int* atr, char* chr) { word w = _vgetw(row, col); *chr = (char)(w & 0xFF); *atr = (int)(w >> 8); } #endif // ------------------------------------------------------------------ // Get character and attribute at cursor position void vgetc(int row, int col, int* atr, vchar* chr) { #if defined(__USE_NCURSES__) chtype charead = mvinch(row, col); *chr = (charead & A_CHARTEXT); *atr = gvid_dosattrcalc(charead & (A_ATTRIBUTES | A_COLOR)); #elif defined(__MSDOS__) if(gvid->isdma()) { _vgetc(row, col, atr, chr); } 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); *chr = cpu.al(); *atr = cpu.ah(); } #elif defined(__OS2__) CHAR tmp[2]; USHORT _row=(USHORT)row, _col=(USHORT)col, len=sizeof(tmp); #if defined(__EMX__) VioReadCellStr((PCH)tmp, &len, _row, _col, 0); #else VioReadCellStr(tmp, &len, _row, _col, 0); #endif *chr = tmp[0]; *atr = tmp[1]; #elif defined(__WIN32__) COORD coord; DWORD x; coord.X = (SHORT) col; coord.Y = (SHORT) row; ReadConsoleOutputAttribute(gvid_hout, (word* ) atr, 1, coord, &x); ReadConsoleOutputCharacter(gvid_hout, (char* ) chr, 1, coord, &x); #elif defined(__UNIX__) _vgetc(row, col, atr, chr); #endif } // ------------------------------------------------------------------ // Scroll screen area #if (defined(__MSDOS__) or defined(__UNIX__)) and not defined(__USE_NCURSES__) 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__) // Currently implemented with vsave/vrestore // Does anyone know a better solution? if(lines >= 0) { if(lines <= 1 + erow - srow) { vatch *buf = vsave(srow + lines, scol, erow, ecol); vrestore(buf, srow, scol, erow - lines, ecol); throw_xfree(buf); } else lines = 1 + erow - srow; for(int counter = 0; counter < lines; counter++) mvhline(1 + erow + counter - lines, scol, ' ' | gvid_attrcalc(atr), 1 + ecol - scol); refresh(); } else { lines*=-1; if(lines <= 1 + erow - srow) { vatch *buf = vsave(srow, scol, erow - lines, ecol); vrestore(buf, srow + lines, scol, erow, ecol); throw_xfree(buf); } else lines = 1 + erow - srow; for(int counter = 0; counter < lines; counter++) mvhline(srow + counter, scol, ' ' | gvid_attrcalc(atr), 1 + ecol - scol); 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__) BYTE tmp[2]; tmp[0] = ' '; tmp[1] = (BYTE)atr; if(lines > 0) VioScrollUp((USHORT)srow, (USHORT)scol, (USHORT)erow, (USHORT)ecol, (USHORT)lines, tmp, 0); else VioScrollDn((USHORT)srow, (USHORT)scol, (USHORT)erow, (USHORT)ecol, (USHORT)-lines, tmp, 0); #elif defined(__WIN32__) CHAR_INFO fill; fill.Char.UnicodeChar = 0; fill.Char.AsciiChar = ' '; fill.Attributes = (WORD)atr; SMALL_RECT r; r.Left = (SHORT)scol; r.Top = (SHORT)srow; r.Right = (SHORT)ecol; r.Bottom = (SHORT)erow; COORD c; c.X = (SHORT)scol; c.Y = (SHORT)(srow - lines); ScrollConsoleScreenBuffer(gvid_hout, &r, &r, c, &fill); #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 if(__vcurhidden) return; COORD c; c.X = (SHORT)col; c.Y = (SHORT)row; 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() { #if defined(__USE_NCURSES__) vclrscr((byte)gvid_dosattrcalc(vgetw(gvid->currow, gvid->curcol))); #else vclrscr((byte)(vgetw(gvid->currow, gvid->curcol) >> 8)); #endif } // ------------------------------------------------------------------ // Clears the screen using given attribute and homes the cursor #if (defined(__MSDOS__) or defined(__UNIX__)) and not defined(__USE_NCURSES__) 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); for(int row = 0; row < LINES; row++) mvhline(row, 0, ' ' | gvid_attrcalc(atr), COLS); 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__) BYTE tmp[2]; tmp[0] = ' '; tmp[1] = (BYTE)atr; VioScrollUp(0, 0, 0xFFFF, 0xFFFF, 0xFFFF, tmp, 0); #elif defined(__WIN32__) COORD c; c.X = c.Y = 0; DWORD wr, len = gvid->numrows * gvid->numcols; 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 #if (defined(__MSDOS__) or defined(__UNIX__)) and not defined(__USE_NCURSES__) 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 vatch* vsave(int __srow, int __scol, int __erow, int __ecol) { if(__srow == -1) __srow = 0; if(__scol == -1) __scol = 0; if(__erow == -1) __erow = gvid->numrows-1; if(__ecol == -1) __ecol = gvid->numcols-1; vatch* sbuf = (vatch*)throw_xcalloc((((__erow-__srow+1)*(__ecol-__scol+1))+4), sizeof(vatch)); if(sbuf) { vatch* buf = sbuf; buf[0] = (vatch)__srow; buf[1] = (vatch)__scol; buf[2] = (vatch)__erow; buf[3] = (vatch)__ecol; #if defined(__USE_NCURSES__) int srow = *buf++; int scol = *buf++; int erow = *buf++; int ecol = *buf++; for(int row=srow; row<=erow; row++) for(int col=scol; col<=ecol; col++) *buf++ = mvinch(row, col); #elif defined(__MSDOS__) int srow = *buf++; int scol = *buf++; int erow = *buf++; int ecol = *buf++; 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__) USHORT srow = *buf++; USHORT scol = *buf++; USHORT erow = *buf++; USHORT ecol = *buf++; USHORT len1 = (USHORT)(ecol-scol+1); #if defined(__BORLANDC__) PCHAR16 ptr = (PCHAR16)buf; #else PCH ptr = (PCH)buf; #endif USHORT len2 = (USHORT)(len1*sizeof(word)); for(USHORT nrow=srow; nrow<=erow; nrow++) { VioReadCellStr(ptr, &len2, nrow, scol, 0); ptr += len2; } #elif defined(__WIN32__) COORD coord; DWORD x; SHORT srow = *buf++; SHORT scol = *buf++; SHORT erow = *buf++; SHORT ecol = *buf++; coord.X = scol; SHORT len1 = (SHORT)(ecol-scol+1); char* p = (char *) buf; for(SHORT nrow=srow; nrow<=erow; nrow++) { coord.Y = nrow; ReadConsoleOutputAttribute(gvid_hout, gvid->bufwrd, len1, coord, &x); ReadConsoleOutputCharacter(gvid_hout, gvid->bufchr, len1, coord, &x); word* q = gvid->bufwrd; char* c = gvid->bufchr; for(int i = 0; i < len1; i++) { *p++ = *c++; *p++ = (byte) *q++; } } #elif defined(__UNIX__) int srow = *buf++; int scol = *buf++; int erow = *buf++; int ecol = *buf++; int len1 = ecol-scol+1; _vsave(buf, len1, srow, scol, erow); #endif } return sbuf; } // ------------------------------------------------------------------ // Redraws a previously saved screen #if (defined(__MSDOS__) or defined(__UNIX__)) and not defined(__USE_NCURSES__) 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 vredraw(vatch* buf, int __srow, int __scol, int __erow, int __ecol) { if(__srow != -1) buf[0] = (vatch)__srow; if(__scol != -1) buf[1] = (vatch)__scol; if(__erow != -1) buf[2] = (vatch)__erow; if(__ecol != -1) buf[3] = (vatch)__ecol; #if defined(__USE_NCURSES__) int srow = *buf++; int scol = *buf++; int erow = *buf++; int ecol = *buf++; for(int row=srow; row<=erow; row++) for(int col=scol; col<=ecol; col++) mvaddch(row, col, *buf++); refresh(); #elif defined(__MSDOS__) int srow = *buf++; int scol = *buf++; int erow = *buf++; int ecol = *buf++; 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 srow = *buf++; USHORT scol = *buf++; USHORT erow = *buf++; USHORT ecol = *buf++; 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__) SHORT srow = *buf++; SHORT scol = *buf++; SHORT erow = *buf++; SHORT ecol = *buf++; SHORT len1 = (SHORT)(ecol-scol+1); for(SHORT nrow=srow; nrow<=erow; nrow++) { vputws(nrow, scol, buf, len1); buf += len1; } #elif defined(__UNIX__) int srow = *buf++; int scol = *buf++; int erow = *buf++; int ecol = *buf++; int len1 = ecol-scol+1; _vredraw(buf, len1, srow, scol, erow); int atr = *buf >> 8; char* color = gvid_newattr(atr); gvid_printf("%s", color); for(int nrow=srow; nrow<=erow; nrow++) { vputansi(nrow, scol, buf, len1); buf += len1; } #endif } // ------------------------------------------------------------------ // Restores a previously saved screen and frees buffer void vrestore(vatch* buf, int srow, int scol, int erow, int ecol) { vredraw(buf, srow, scol, erow, ecol); } // ------------------------------------------------------------------ // 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) 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); 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 // ------------------------------------------------------------------ #if not defined(__USE_NCURSES__) 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 "ÚÄ¿³³ÀÄÙÅôÂÁ°±", // 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 #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 // ------------------------------------------------------------------ #if defined(__UNIX__) and not defined(__USE_NCURSES__) void gvid_boxcvt(char* s) { while(*s) { switch(*s) { case 'Ú': *s = _box_table(8, 0); break; case 'Ä': *s = _box_table(8, 1); break; case '¿': *s = _box_table(8, 2); break; case '³': *s = _box_table(8, 4); break; case 'À': *s = _box_table(8, 5); break; case 'Ù': *s = _box_table(8, 7); break; case 'Å': *s = _box_table(8, 8); break; case 'Ã': *s = _box_table(8, 9); break; case '´': *s = _box_table(8, 10); break; case 'Â': *s = _box_table(8, 11); break; case 'Á': *s = _box_table(8, 12); break; } s++; } } #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); } // ------------------------------------------------------------------ // Gets the character part of a character-attribute group vchar vgchar (vatch chat) { #if defined(__USE_NCURSES__) return chat & (A_CHARTEXT | A_ALTCHARSET); #else return chat & 0xff; #endif } // ------------------------------------------------------------------ // Gets the attribute part of a character-attribute group int vgattr (vatch chat) { #if defined(__USE_NCURSES__) return gvid_dosattrcalc(chat); #else return (chat >> 8) & 0xff; #endif } // ------------------------------------------------------------------ // Sets the given character in a character-attribute group vatch vschar (vatch chat, vchar chr) { #if defined(__USE_NCURSES__) return (chr&(A_CHARTEXT|A_ALTCHARSET))|(chat&~(A_CHARTEXT|A_ALTCHARSET)); #else return (chat & 0xff00) | chr; #endif } // ------------------------------------------------------------------ // Sets the given attribute in a character-attribute group vatch vsattr (vatch chat, int atr) { #if defined(__USE_NCURSES__) return (chat & (A_CHARTEXT | A_ALTCHARSET)) | gvid_attrcalc(atr); #else return (chat & 0xff) | (atr << 8); #endif } // ------------------------------------------------------------------ // Compose character-attribute group from character and attribute vatch vcatch (vchar chr, int atr) { #if defined(__USE_NCURSES__) return chr | gvid_attrcalc(atr); #else return (chr & 0xff) | ((atr << 8) & 0xff00) ; #endif } // ------------------------------------------------------------------