/* * IBMSCRN.C * * Written on 10-Jul-94 by John Dennis and released to the public domain. * * Screen definitions and routines for the IBM PC only; EGA/VGA support * not using a commercial screen product. * * Uses an event queue for mouse and keyboard input. Currently doesn't ask * ask for a DESQview buffer and doesn't give up any ticks - this should be * implemented in some compiler independant fashion. */ #ifndef PACIFIC #include #include #endif #ifdef __DJGPP__ #include #endif #if defined(__TURBOC__) || defined(_MSC_VER) #include #endif #if defined(__WATCOMC__) #include #include #endif #include #include "winsys.h" #include "vio.h" #include "dosasm.h" #include "unused.h" #include "specch.h" /* codepage 437 / 850 block graphics */ char *tt_specials="\272\315\311\273\310\274\263\304\332\277\300\331\261\020\021\334\337\030\031\024\035\000"; #define EBUFSZ 100 #define TERMDEF 1 #define NCOL 80 #define NROW 25 TERM term = { NCOL, NROW, 0, }; unsigned int color; int LButton = 0; int RButton = 0; int cur_start = 6; /* these are ega/vga defaults */ int cur_end = 7; static EVT EVent[EBUFSZ]; /* event circular queue */ static int ebufin = 0; /* event in */ static int ebufout = 0; /* event out */ static MOU mstatus = {0, 40, 12, 0, 0, 1, 1, 0}; /* mouse status */ static int mouse_avail = 0; static int mousex = 40; static int mousey = 12; static int mykbhit(void); static int FullBuffer(void); void TTBeginOutput(void) {} void TTEndOutput(void) {} int TTScolor(unsigned int Attr) { VIOsetfore(Attr & 0x000f); VIOsetback((Attr & 0x00f0) / 0x10); color = Attr & 0x00ff; return 0; } int TTCurSet(int st) { #ifdef __DJGPP__ __dpmi_regs regs; #else union REGS regs; #endif if (st) { /* restore cursor */ regs.h.ah = 0x01; regs.h.ch = cur_start; regs.h.cl = cur_end; #if defined(__DJGPP__) __dpmi_int(0x10, ®s); #elif defined(MSDOS) && (defined(__FLAT__) || defined(__386__)) int386(0x10, ®s, ®s); #else int86(0x10, ®s, ®s); #endif } else { /* hide cursor */ regs.h.ah = 0x01; regs.h.ch = 0x20; #if defined(__DJGPP__) __dpmi_int(0x10, ®s); #elif defined(MSDOS) && (defined(__FLAT__) || defined(__386__)) int386(0x10, ®s, ®s); #else int86(0x10, ®s, ®s); #endif } return 0; } int TTgotoxy(int row, int col) { VIOgotoxy(col, row); VIOupdate(); return 0; } int TTgetxy(int *row, int *col) { *row = VIOwherex(); *col = VIOwherey(); return 0; } unsigned int TTGetKey(void) { return obtkey(); } int TTPutChr(unsigned int Ch) { VIOputc(Ch); VIOupdate(); return 0; } int TTWriteStr(unsigned long *b, int len, int row, int col) { unsigned short *buf = malloc(len * sizeof(unsigned short)); int i; if (buf != NULL) { for (i = 0; i < len; i++) { buf[i] = (unsigned short)((b[i] & 0xFFUL) | ((b[i] >> 8) & 0xFF00UL)); } VIOputr(col, row, len, 1, buf); free(buf); } return 0; } int TTStrWr(unsigned char *s, int row, int col, int len) { unsigned long line[200]; int i = 0; unused(len); while (*s && i < sizeof(line)) { line[i] = ((unsigned long)(*s) & 0xffUL) | (((unsigned long)color) << 16); s++; i++; } TTWriteStr(line, i, row, col); return 0; } int TTReadStr(unsigned long *b, int len, int row, int col) { int i; unsigned short * bc = (unsigned short *)b; VIOgetra(col, row, col + len - 1, row, bc); for (i = len - 1; i >= 0; i--) { b[i] = MAKECELL(bc[i] & 0xFF, (bc[i] >> 8) & 0xFF); } return 0; } int TTClear(int x1, int y1, int x2, int y2) { VIOclear(x1, y1, x2, y2); return 0; } int TTScroll(int x1, int y1, int x2, int y2, int lines, int Dir) { if (Dir) { VIOscrollup(x1, y1, x2 + 1, y2, lines); } else { VIOscrolldown(x1, y1, x2 + 1, y2, lines); } return 0; } int TTEeol(void) { int row, col; TTgetxy(&row, &col); TTScroll(col, row, NCOL - 1, row, 0, 1); return 0; } int TTdelay(int mil) { #ifdef __TURBOC__ delay(mil); #else unused(mil); #endif return 0; } void TTSendMsg(int msg, int x, int y, int msgtype) { if (((ebufin + 1) % EBUFSZ) != ebufout) { EVent[ebufin].msg = msg; EVent[ebufin].x = x; EVent[ebufin].y = y; EVent[ebufin].msgtype = msgtype; ebufin = (ebufin + 1) % EBUFSZ; } } /* * This is primarily the input section of the file. All messages * are handled here. */ #define CLICKMAX 50 /* second max */ #define REPEAT_PAUSE 800 #define T_DOS 1 #define T_DV 2 #define T_DPMI 3 int ms_reset(int *mousetype); int ms_show_cursor(void); int ms_hide_cursor(void); int ms_get_mouse_pos(int *horizpos, int *vertpos); static unsigned long rtimer = -1; static unsigned long ltimer = -1; static int mtask = T_DOS; void pause(void) { switch (mtask) { case T_DOS: dospause(); break; case T_DV: dvpause(); break; case T_DPMI: dpmipause(); break; default: break; } } static unsigned long hsec_time(void) { static unsigned long old_id = 0; unsigned long i; #if defined(__TURBOC__) struct time t; gettime(&t); i = (t.ti_sec * 100L) + t.ti_hund; #elif defined(PACIFIC) i = 0; #else struct dostime_t dtime; _dos_gettime(&dtime); i = (dtime.second * 100L) + dtime.hsecond; #endif old_id = i; return i; } /* * We should give up some ticks here. Typically when polling this * routine it is quite possible to loop through this in less than a * millisecond. Obviuosly this resolution is not needed :-) */ int collect_events(void) { static int oy = 0, ox = 0; int moved = 0; int evt = 0; int ret; if (mouse_avail) { ret = ms_get_mouse_pos(&mousex, &mousey); if (mousex != ox || mousey != oy) { ox = mstatus.x = mousex; oy = mstatus.y = mousey; moved = 1; } if (mstatus.lrelease && (ret & 1)) { evt = 1; mstatus.lbutton = 1; mstatus.lrelease = 0; ltimer = hsec_time() + CLICKMAX; TTSendMsg(MOU_LBTDN, ox, oy, WND_WM_MOUSE); } if (mstatus.lbutton && !(ret & 1)) { evt = 1; mstatus.lbutton = 0; mstatus.lrelease = 1; TTSendMsg(MOU_LBTUP, ox, oy, WND_WM_MOUSE); if (hsec_time() < ltimer) { TTSendMsg(LMOU_CLCK, ox, oy, WND_WM_MOUSE); } } if (mstatus.rrelease && (ret & 2)) { evt = 1; mstatus.rbutton = 1; mstatus.rrelease = 0; rtimer = hsec_time() + CLICKMAX; TTSendMsg(MOU_RBTDN, ox, oy, WND_WM_MOUSE); } if (mstatus.rbutton && !(ret & 2)) { evt = 1; mstatus.rbutton = 0; mstatus.rrelease = 1; TTSendMsg(MOU_RBTUP, ox, oy, WND_WM_MOUSE); if (hsec_time() < rtimer) { TTSendMsg(RMOU_CLCK, ox, oy, WND_WM_MOUSE); } } if (!evt) { if (mstatus.lbutton || mstatus.rbutton) { if (mstatus.lbutton && hsec_time() > ltimer) { TTSendMsg(LMOU_RPT, ox, oy, WND_WM_MOUSE); } if (mstatus.rbutton && hsec_time() > rtimer) { TTSendMsg(RMOU_RPT, ox, oy, WND_WM_MOUSE); } if (moved) { TTSendMsg(MOUSE_EVT, ox, oy, WND_WM_MOUSE); } } } if (mykbhit()) { TTSendMsg(TTGetKey(), 0, 0, WND_WM_CHAR); } } else if (mykbhit()) { TTSendMsg(TTGetKey(), 0, 0, WND_WM_CHAR); } return 0; } int TTGetMsg(EVT * event) { while (ebufin == ebufout) { pause(); collect_events(); } event->msg = EVent[ebufout].msg; event->msgtype = EVent[ebufout].msgtype; event->x = EVent[ebufout].x; event->y = EVent[ebufout].y; event->id = 0; ebufout = (ebufout + 1) % EBUFSZ; return event->msg; } int TTPeekQue(void) { collect_events(); return (ebufin != ebufout); } void TTClearQue(void) { ebufin = ebufout; } int TTGetChr(void) { EVT e; TTGetMsg(&e); return e.msg; } void MouseON(void) { if (mouse_avail) { ms_show_cursor(); } } void MouseOFF(void) { if (mouse_avail) { ms_hide_cursor(); } } int GetMouInfo(int *x, int *y) { if (mouse_avail) { ms_get_mouse_pos(&mousex, &mousey); *x = mousex; *y = mousey; } else { *x = *y = 0; } return 0; } int TTKopen(void) { return 0; } int TTKclose(void) { return 0; } int TTclose(void) { if (mouse_avail) { ms_hide_cursor(); } VIOclose(); return 0; } #pragma warn -par /* * Configure the terminal. This must be called *before* TTopen! * * The DOS/BIOS terminal does not need any configuration. * */ int TTconfigure(const char *keyword, const char *value) { return 0; } #pragma warn +par int dv_running(void) { return dvcheck(); } int TTopen(void) { int m = 0; if (dv_running()) { mtask = T_DV; } else if (dpmicheck()) { mtask = T_DPMI; } VIOopen(); term.NRow = VIOrows(); term.NCol = VIOcolumns(); TTScolor(0x07); mouse_avail = 0; if (!(term.Abil & NOMOUSE)) { if (ms_reset(&m)) { if (m != 0) { mouse_avail = 1; MouseON(); ms_get_mouse_pos(&mousex, &mousey); } } } return 0; } static int mykbhit(void) { if (FullBuffer()) { return (0); } return kbdhit(); } static int FullBuffer(void) { return ((ebufin + 1) % EBUFSZ) != ebufout ? 0 : 1; }