/* * * $Id: term.dos 7281 2004-04-05 01:06:15Z amk $ * * 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 #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 (celllCell) 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