649 lines
13 KiB
Plaintext
649 lines
13 KiB
Plaintext
/*
|
|
*
|
|
* $Id: term.dos 7884 1998-02-28 00:15:44Z hubert $
|
|
*
|
|
* Program: IBM PC specific routine
|
|
*
|
|
*
|
|
* Michael Seibel
|
|
* Networks and Distributed Computing
|
|
* Computing and Communications
|
|
* University of Washington
|
|
* Administration Builiding, AG-44
|
|
* Seattle, Washington, 98195, USA
|
|
* Internet: mikes@cac.washington.edu
|
|
*
|
|
* Please address all bugs and comments to "pine-bugs@cac.washington.edu"
|
|
*
|
|
*
|
|
* Pine and Pico are registered trademarks of the University of Washington.
|
|
* No commercial use of these trademarks may be made without prior written
|
|
* permission of the University of Washington.
|
|
*
|
|
* Pine, Pico, and Pilot software and its included text are Copyright
|
|
* 1989-1998 by the University of Washington.
|
|
*
|
|
* The full text of our legal notices is contained in the file called
|
|
* CPYRIGHT, included with this distribution.
|
|
*
|
|
*/
|
|
|
|
/*
|
|
* The routines in this file provide support for the IBM-PC and other
|
|
* compatible terminals. It goes directly to the graphics RAM to do
|
|
* screen output. It compiles into nothing if not an IBM-PC driver
|
|
*/
|
|
|
|
#include <conio.h>
|
|
#if IBMPC
|
|
#define termdef 1 /* don't define "term" external */
|
|
|
|
int ibmmove PROTO((int, int));
|
|
int ibmeeol PROTO((void));
|
|
int ibmputc PROTO((int));
|
|
int ibmoutc PROTO((char));
|
|
int ibmeeop PROTO((void));
|
|
int ibmrev PROTO((int));
|
|
void beep PROTO((unsigned int, unsigned int));
|
|
int cutebeep PROTO((void));
|
|
int ibmbeep PROTO((void));
|
|
int ibmopen PROTO((void));
|
|
int ibmclose PROTO((void));
|
|
|
|
|
|
#define MARGIN 8 /* size of minimim margin and */
|
|
#define SCRSIZ 64 /* scroll size for extended lines */
|
|
#define MROW 2 /* rows in menu */
|
|
|
|
|
|
#define SET_COLOR(fore,back) ((((back) & 0xf) << 4) | ((fore) & 0xf))
|
|
|
|
int nfcolor = 7; /* current forground color */
|
|
int nbcolor = 1; /* current background color */
|
|
int rfcolor = 0; /* reverse forground color */
|
|
int rbcolor = 3; /* reverse background color */
|
|
unsigned cattr; /* current combined attribute */
|
|
|
|
/*
|
|
* Standard terminal interface dispatch table. Most of the fields point into
|
|
* "termio" code.
|
|
*/
|
|
TERM term = {
|
|
NROW-1,
|
|
NCOL,
|
|
MARGIN,
|
|
SCRSIZ,
|
|
MROW,
|
|
ibmopen,
|
|
NULL,
|
|
ibmclose,
|
|
ttgetc,
|
|
ibmputc,
|
|
ttflush,
|
|
ibmmove,
|
|
ibmeeol,
|
|
ibmeeop,
|
|
ibmbeep,
|
|
ibmrev
|
|
};
|
|
|
|
|
|
#ifdef DOS
|
|
extern union REGS rg;
|
|
static unsigned display_mode; /* */
|
|
#endif
|
|
|
|
|
|
static char *colist[] = {
|
|
"black",
|
|
"blue",
|
|
"green",
|
|
"cyan",
|
|
"red",
|
|
"magenta",
|
|
"yellow",
|
|
"white",
|
|
"BLACK",
|
|
"BLUE",
|
|
"GREEN",
|
|
"CYAN",
|
|
"RED",
|
|
"MAGENTA",
|
|
"YELLOW",
|
|
"WHITE" };
|
|
|
|
/*
|
|
* pico_setcolor - given the color name, return the color's value
|
|
*/
|
|
int
|
|
setcolor(s)
|
|
char *s;
|
|
{
|
|
int i;
|
|
|
|
for (i=0; i<16; i++)
|
|
if (!strcmp(colist[i],s))
|
|
return(i);
|
|
|
|
return(7);
|
|
}
|
|
|
|
|
|
/*
|
|
* pico_XXcolor() - each function sets a particular attribute
|
|
*/
|
|
pico_nfcolor(s)
|
|
char *s;
|
|
{
|
|
nfcolor = setcolor(s);
|
|
}
|
|
|
|
pico_nbcolor(s)
|
|
char *s;
|
|
{
|
|
nbcolor = setcolor(s);
|
|
}
|
|
|
|
pico_rfcolor(s)
|
|
char *s;
|
|
{
|
|
rfcolor = setcolor(s);
|
|
}
|
|
|
|
pico_rbcolor(s)
|
|
char *s;
|
|
{
|
|
rbcolor = setcolor(s);
|
|
}
|
|
|
|
#ifdef OS2
|
|
static VIOMODEINFO display_mode;
|
|
static BYTE *oldscreen =NULL;
|
|
static USHORT origRow, origCol;
|
|
static USHORT origLen =0;
|
|
#ifdef FASTVIO
|
|
extern HMOU Mouse_Handle;
|
|
extern int mouse_state;
|
|
static int was_mouse_state=-1;
|
|
static int _moved=0, _line=0, _col=0;
|
|
static USHORT usVidbufLength =0;
|
|
static USHORT usRows =0, usCols =0;
|
|
static USHORT * pusVidBuffer =NULL;
|
|
static USHORT fCell=(USHORT)-1,
|
|
lCell=(USHORT)-1;
|
|
|
|
static HEV hvUpdate =(HEV)0;
|
|
static HMTX hxUpdate =(HMTX)0;
|
|
static TID threadID;
|
|
static NOPTRRECT noptr = { 0, 0, (USHORT)-1, (USHORT)-1 };
|
|
|
|
static void update_thread(ULONG args)
|
|
{
|
|
while (DosWaitEventSem(hvUpdate, -1)==0) {
|
|
DosResetEventSem(hvUpdate, &args);
|
|
if (fCell!=(USHORT)-1) {
|
|
DosRequestMutexSem(hxUpdate,-1);
|
|
if (was_mouse_state && Mouse_Handle!=(HMOU)-1)
|
|
MouRemovePtr(&noptr, Mouse_Handle);
|
|
/* Update the screen, if required */
|
|
VioShowBuf(fCell*2,(lCell-fCell+1)*2, 0);
|
|
fCell=lCell=(USHORT)-1;
|
|
DosReleaseMutexSem(hxUpdate);
|
|
if (mouse_state && Mouse_Handle!=(HMOU)-1)
|
|
MouDrawPtr(Mouse_Handle);
|
|
}
|
|
else if (mouse_state != was_mouse_state && Mouse_Handle!=(HMOU)-1) {
|
|
if (mouse_state)
|
|
MouDrawPtr(Mouse_Handle);
|
|
else
|
|
MouRemovePtr(&noptr, Mouse_Handle);
|
|
}
|
|
was_mouse_state=mouse_state;
|
|
if (_moved) {
|
|
_moved=0;
|
|
VioSetCurPos((USHORT)_line,(USHORT)_col,0);
|
|
}
|
|
DosSleep(1);
|
|
}
|
|
}
|
|
|
|
static void vidCell(USHORT row, USHORT col)
|
|
{
|
|
USHORT cell=(row*usCols)+col;
|
|
|
|
DosRequestMutexSem(hxUpdate,-1);
|
|
/* Always update first cell */
|
|
if (fCell==(USHORT)-1)
|
|
fCell=lCell=cell;
|
|
else {
|
|
/* Otherwise stretch limits if necessary */
|
|
if (cell<fCell)
|
|
fCell=cell;
|
|
if (cell>lCell)
|
|
lCell=cell;
|
|
}
|
|
DosReleaseMutexSem(hxUpdate);
|
|
}
|
|
|
|
/* These seek to do minimal screen update
|
|
* by keeping track of the first and last
|
|
* cells written to the video buffer
|
|
*/
|
|
|
|
void vidUpdate()
|
|
{
|
|
if (hvUpdate == (HEV)0) {
|
|
VIOMODEINFO mi;
|
|
|
|
DosCreateEventSem(NULL, &hvUpdate, 0, FALSE);
|
|
DosCreateMutexSem(NULL, &hxUpdate, 0, FALSE);
|
|
DosCreateThread(&threadID,update_thread,0,0,8192);
|
|
mi.cb = sizeof mi;
|
|
VioGetMode(&mi, 0);
|
|
noptr.cRow = mi.row-1;
|
|
noptr.cCol = mi.col-1;
|
|
}
|
|
DosPostEventSem(hvUpdate);
|
|
}
|
|
|
|
static void vidArea(USHORT frow, USHORT fcol, USHORT lrow, USHORT lcol)
|
|
{
|
|
vidCell(frow,fcol);
|
|
vidCell(lrow,lcol);
|
|
}
|
|
#endif
|
|
#endif
|
|
|
|
|
|
/*
|
|
* ibmmove - Use BIOS video services, function 2h to set cursor postion
|
|
*/
|
|
ibmmove(row, col)
|
|
int row, col;
|
|
{
|
|
#ifdef OS2
|
|
#ifdef FASTVIO
|
|
if (_line!=row || _col!=col) {
|
|
_line=row;
|
|
_col=col;
|
|
_moved=1;
|
|
}
|
|
#else
|
|
VioSetCurPos((USHORT)row, (USHORT)col, 0);
|
|
#endif
|
|
#else
|
|
rg.h.ah = 2; /* set cursor position function code */
|
|
rg.h.bh = 0; /* set screen page number */
|
|
rg.h.dl = col;
|
|
rg.h.dh = row;
|
|
int86(BIOS_VIDEO, &rg, &rg);
|
|
#endif
|
|
}
|
|
|
|
|
|
/*
|
|
* ibmeeol - erase to the end of the line
|
|
*/
|
|
ibmeeol()
|
|
{
|
|
#ifdef OS2
|
|
USHORT row, col;
|
|
BYTE chattr[2];
|
|
chattr[0] = ' ';
|
|
chattr[1] = (BYTE)cattr;
|
|
|
|
#ifdef FASTVIO
|
|
row=(USHORT)_line;
|
|
col=(USHORT)_col;
|
|
vidCell(row,col);
|
|
vidCell(row,usCols-1);
|
|
row=(row*usCols)+col;
|
|
col=usCols-col;
|
|
while(col--)
|
|
pusVidBuffer[row++] = *(USHORT *)chattr;
|
|
#else
|
|
/* find the current cursor position */
|
|
VioGetCurPos(&row, &col, 0);
|
|
VioWrtNCell(chattr, NCOL-col, row, col, 0);
|
|
#endif
|
|
#else
|
|
int col, row, page;
|
|
|
|
/* find the current cursor position */
|
|
rg.h.ah = 3; /* read cursor position function code */
|
|
int86(BIOS_VIDEO, &rg, &rg);
|
|
page = rg.h.bh;
|
|
col = rg.h.dl; /* record current column */
|
|
row = rg.h.dh; /* and row */
|
|
|
|
rg.h.ah = 0x09; /* write char to screen with new attrs */
|
|
rg.h.al = ' ';
|
|
rg.h.bl = cattr;
|
|
rg.h.bh = page;
|
|
rg.x.cx = NCOL-col;
|
|
int86(BIOS_VIDEO, &rg, &rg);
|
|
#endif
|
|
}
|
|
|
|
|
|
/*
|
|
* ibmputc - put a character at the current position in the
|
|
* current colors
|
|
*/
|
|
ibmputc(ch)
|
|
int ch;
|
|
{
|
|
#ifdef OS2
|
|
USHORT row, col;
|
|
|
|
/* first, get current position */
|
|
#ifdef FASTVIO
|
|
row=(USHORT)_line;
|
|
col=(USHORT)_col;
|
|
#else
|
|
VioGetCurPos(&row, &col, 0);
|
|
#endif
|
|
if (ch == '\b') {
|
|
if (col > 0)
|
|
ibmmove(row, --col);
|
|
}
|
|
else {
|
|
BYTE chattr[2];
|
|
chattr[0]=(BYTE)ch;
|
|
chattr[1]=(BYTE)cattr;
|
|
#if FASTVIO
|
|
vidCell(row,col);
|
|
pusVidBuffer[(row*usCols)+col] = *(USHORT *)chattr;
|
|
if (col < usCols)
|
|
#else
|
|
VioWrtNCell(chattr, 1, row, col, 0);
|
|
if (col < NCOL)
|
|
#endif
|
|
ibmmove(row, ++col);
|
|
}
|
|
#else
|
|
int col, row, page;
|
|
|
|
rg.h.ah = 0x03; /* first, get current position */
|
|
int86(BIOS_VIDEO, &rg, &rg);
|
|
page = rg.h.bh;
|
|
row = rg.h.dh;
|
|
col = rg.h.dl;
|
|
|
|
if(ch == '\b'){
|
|
if(col > 0) /* advance the cursor */
|
|
ibmmove(row, --col);
|
|
}
|
|
else{
|
|
rg.h.ah = 0x09; /* write char to screen with new attrs */
|
|
rg.h.al = ch;
|
|
rg.h.bl = cattr; /* inverting if needed */
|
|
rg.h.bh = page;
|
|
rg.x.cx = 1; /* only once */
|
|
int86(BIOS_VIDEO, &rg, &rg);
|
|
|
|
if(col < 80) /* advance the cursor */
|
|
ibmmove(row, ++col);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
|
|
/*
|
|
* ibmgetc - output a single character with the right attributes, but
|
|
* don't advance the cursor
|
|
*/
|
|
ibmgetc(c)
|
|
char *c;
|
|
{
|
|
#ifdef OS2
|
|
/* first, get current position */
|
|
#if FASTVIO
|
|
*c=(BYTE)pusVidBuffer[(_line*usCols)+_col];
|
|
#else
|
|
USHORT row, col, n = 1;
|
|
|
|
VioGetCurPos(&row, &col, 0);
|
|
VioReadCharStr(c, 1, &n, row, col, 0);
|
|
#endif
|
|
#else
|
|
rg.h.ah = 8; /* vid services, read char at cursor */
|
|
rg.h.bh = 0;
|
|
int86(0x10, &rg, &rg);
|
|
*c = rg.h.al;
|
|
#endif
|
|
}
|
|
|
|
|
|
/*
|
|
* ibmeeop - clear from cursor to end of page
|
|
*/
|
|
ibmeeop()
|
|
{
|
|
#ifdef OS2
|
|
#if FASTVIO
|
|
USHORT atofs;
|
|
#endif
|
|
BYTE chattr[2];
|
|
chattr[0] = ' ';
|
|
chattr[1] = (BYTE)cattr;
|
|
|
|
#ifdef FASTVIO
|
|
vidArea(0,0,usRows-1,usCols-1);
|
|
for (atofs=0; atofs < usVidbufLength;++atofs)
|
|
pusVidBuffer[atofs] = *(USHORT *)chattr;
|
|
#else
|
|
VioScrollUp(0, 0, -1, -1, -1, chattr, 0);
|
|
#endif
|
|
#else
|
|
rg.h.ah = 6; /* scroll page up function code */
|
|
rg.h.al = 0; /* # lines to scroll (clear it) */
|
|
rg.x.cx = 0; /* upper left corner of scroll */
|
|
rg.x.dx = (term.t_nrow << 8) | (term.t_ncol - 1);
|
|
rg.h.bh = cattr;
|
|
int86(BIOS_VIDEO, &rg, &rg);
|
|
#endif
|
|
ibmmove(0, 0);
|
|
}
|
|
|
|
|
|
/*
|
|
* ibmrev - change reverse video state
|
|
*/
|
|
ibmrev(state)
|
|
int state;
|
|
{
|
|
cattr = (state) ? SET_COLOR(rfcolor, rbcolor)
|
|
: SET_COLOR(nfcolor, nbcolor);
|
|
}
|
|
|
|
|
|
/*
|
|
* getrevstate - return the current reverse state
|
|
*/
|
|
getrevstate()
|
|
{
|
|
return(cattr == SET_COLOR(rfcolor, rbcolor));
|
|
}
|
|
|
|
|
|
/*
|
|
* beep - make the speaker sing!
|
|
*/
|
|
void
|
|
beep(freq, dur)
|
|
unsigned freq, dur;
|
|
{
|
|
#ifdef OS2
|
|
if (freq)
|
|
DosBeep(freq, dur);
|
|
#else
|
|
unsigned oport;
|
|
|
|
if(!freq)
|
|
return;
|
|
|
|
freq = (unsigned)(1193180 / freq);
|
|
/* set up the timer */
|
|
outp(0x43, 0xb6); /* set timer channel 2 registers */
|
|
outp(0x42, (0xff&freq)); /* low order byte of count */
|
|
outp(0x42, (freq>>8)); /* hi order byte of count */
|
|
|
|
/* make the sound */
|
|
oport = inp(0x61);
|
|
outp(0x61, oport | 0x03);
|
|
ssleep((clock_t)((dur < 75) ? 75 : dur));
|
|
outp(0x61, oport);
|
|
#endif
|
|
}
|
|
|
|
|
|
/*
|
|
* cutebeep - make the speeker sing the way we want!
|
|
*/
|
|
cutebeep()
|
|
{
|
|
beep(575, 50);
|
|
#ifndef OS2
|
|
ssleep((clock_t)25);
|
|
#endif
|
|
beep(485, 90);
|
|
}
|
|
|
|
|
|
/*
|
|
* ibmbeep - system beep...
|
|
*/
|
|
ibmbeep()
|
|
{
|
|
cutebeep();
|
|
}
|
|
|
|
|
|
/*
|
|
* enter_text_mode - get current video mode, saving to be restored
|
|
* later, then explicitly set 80 col text mode.
|
|
*
|
|
* NOTE: this gets kind of weird. Both pine and pico call this
|
|
* during initialization. To make sure it's only invoked once
|
|
* it only responds if passed NULL which pico only does if not
|
|
* called from in pine, and pine does all the time. make sense?
|
|
* thought not.
|
|
*/
|
|
void
|
|
enter_text_mode(p)
|
|
PICO *p;
|
|
{
|
|
#ifdef OS2
|
|
if (!p) {
|
|
#ifdef FASTVIO
|
|
ULONG pBuf;
|
|
#endif
|
|
display_mode.cb = sizeof display_mode;
|
|
VioGetMode(&display_mode, 0);
|
|
term.t_ncol = display_mode.col;
|
|
term.t_nrow = display_mode.row - 1;
|
|
origLen = display_mode.row * display_mode.col * sizeof(USHORT);
|
|
if (oldscreen)
|
|
free(oldscreen);
|
|
oldscreen = malloc(origLen);
|
|
if (oldscreen)
|
|
VioReadCellStr(oldscreen, &origLen, 0, 0, 0);
|
|
VioGetCurPos(&origRow, &origCol, 0);
|
|
#ifdef FASTVIO
|
|
_line=origRow;
|
|
_col=origCol;
|
|
#endif
|
|
#ifdef FASTVIO
|
|
usRows = display_mode.row;
|
|
usCols = display_mode.col;
|
|
VioGetBuf(&pBuf,&usVidbufLength,0);
|
|
pusVidBuffer = _emx_16to32((_far16ptr)pBuf);
|
|
/* OS2 2.1+ VIO bug (viobuf not initialised) workaround */
|
|
memcpy(pusVidBuffer,oldscreen,usVidbufLength);
|
|
usVidbufLength /= 2; /* Cells, not bytes */
|
|
#endif
|
|
}
|
|
#else
|
|
static int i = 0;
|
|
if(!p && !i++){
|
|
rg.h.ah = 0x0f; /* save old mode */
|
|
int86(BIOS_VIDEO, &rg, &rg);
|
|
display_mode = rg.h.al;
|
|
|
|
rg.h.ah = 0; /* then set text mode */
|
|
rg.h.al = 2;
|
|
int86(BIOS_VIDEO, &rg, &rg); /* video services */
|
|
}
|
|
#endif
|
|
}
|
|
|
|
|
|
/*
|
|
* exit_text_mode - leave text mode by restoring saved original
|
|
* video mode.
|
|
*/
|
|
void
|
|
exit_text_mode(p)
|
|
PICO *p;
|
|
{
|
|
|
|
#ifdef OS2
|
|
if (!p) {
|
|
turnmouseoff(); /* Make sure mouse is off while display is updated */
|
|
VioSetMode(&display_mode, 0);
|
|
if (!oldscreen)
|
|
{
|
|
ibmeeop();
|
|
VioSetCurPos(display_mode.row-1, 0, 0);
|
|
}
|
|
else
|
|
{
|
|
VioWrtCellStr(oldscreen, origLen, 0, 0, 0);
|
|
VioSetCurPos(origRow, origCol, 0);
|
|
}
|
|
}
|
|
#else
|
|
static int i = 0;
|
|
if(!p && !i++){ /* called many, invoke once! */
|
|
rg.h.ah = 0; /* just restore old mode */
|
|
rg.h.al = display_mode;
|
|
int86(BIOS_VIDEO, &rg, &rg);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
|
|
/*
|
|
* ibmopen - setup text mode and setup key labels...
|
|
*/
|
|
ibmopen()
|
|
{
|
|
|
|
enter_text_mode(Pmaster);
|
|
|
|
cattr = SET_COLOR(nfcolor, nbcolor);
|
|
revexist = TRUE;
|
|
inschar = delchar = 0;
|
|
|
|
ttopen();
|
|
}
|
|
|
|
|
|
ibmclose()
|
|
{
|
|
#if COLOR
|
|
ibmfcol(7);
|
|
ibmbcol(0);
|
|
#endif
|
|
#ifdef MOUSE
|
|
mouseoff();
|
|
#endif
|
|
exit_text_mode(Pmaster);
|
|
|
|
ttclose();
|
|
}
|
|
#endif
|
|
|
|
|