/* * portdos.c: Portable calls for DOS * ================================== * (C)1996 by F.Jalvingh; Public domain. * (C)1997 by Markus F.X.J. Oberhumer; Public domain. * * $Header: /cvsroot/fte/fte/src/portdos.c,v 1.1.1.1 2000/01/30 17:23:45 captnmark Exp $ * * $Log: portdos.c,v $ * Revision 1.1.1.1 2000/01/30 17:23:45 captnmark * initial import * */ #include "port.h" #include #include #if defined(DOS) || defined(DOSP32) #include #if defined(__DJGPP__) #include #include #include #include #define inp inportb #define outp outportb #endif struct plScnInfo { int s_inited; // T when current status is known. int s_wid, s_hig; // Current screen size enum ePlScnType s_type; // Current screen type, boolean s_ismono; // T when black- and white. boolean s_isbright; //** Cursor info, boolean s_curinit; boolean s_curon; // T when cursor is visible int s_cur_x, s_cur_y; // Current cursor position, int s_curstart, // Start of cursor blob, s_curend; // End of blob; UWORD s_iobase; #if defined(__DOS4G__) || defined(__DJGPP__) ULONG s_pbase; // Physical base address of video memory #else UWORD s_pseg; // Segment of video memory #endif }; /*--------------------------------------------------------------------------*/ /* STATIC GLOBALS.. */ /*--------------------------------------------------------------------------*/ static struct plScnInfo plScnI; static void plScnInit(void); /* * between() returns a # between bounds. */ static int between(int x, int low, int hig) { if(x < low) return low; else if(x > hig) return hig; return x; } /****************************************************************************/ /* */ /* CODING: Screen type determination for DOS.. */ /* */ /****************************************************************************/ /* * This is very important for the working of the DOS interface. It determines * the screen type, and derives some stuff from that: * - screen base address (i/o port) * - video memory address (for direct I/O to the screen). */ /* * VgaMonoMonitor() returns T if the monitor attached to a VGA adaptor is a * monochrome monitor. */ static boolean VgaMonoMonitor(void) { union dosxReg r; memset(&r, 0, sizeof(r)); // Clear all unused regs, r.w.ax = 0x1a00; // Function 1A subfunction 00 dosxIntr(0x10, &r); // Call VGA BIOS, if(r.h.al != 0x1a) return FALSE; // Assume color if call not supported, if(r.h.bl == 0x01 || r.h.bl == 0x05 || r.h.bl == 0x07 ||r.h.bl == 0x0B) return TRUE; // These types are MONO, else return FALSE; } /* * biosisVGA() returns TRUE if a VGA-card is found. */ static boolean biosisVGA(void) { boolean isvga; outp(0x3ce, 8); // Bit mask register, outp(0x3cf, 1); // Test mask, (1) outp(0x3ce, 8); // Bit mask register again, if(inp(0x3cf) == 1) // Can we read the same value? isvga = TRUE; // Yes -> is VGA! else isvga = FALSE; outp(0x3ce, 8); // Bit mask register last time, outp(0x3cf, 0xff); // All on (default value) return isvga; } /* * biosisEGA() returns TRUE if the card is an EGA card (or a VGA card). */ static boolean biosisEGA(void) { union dosxReg r; UBYTE ega; //** Get EGA BIOS byte. dosxMemRead(&ega, 0x00400087ul, 1); // Read EGA BIOS sysvar, if(! (ega & 0x08)) // There's an active EGA in the system! { //** EGA is active: do EGA bios call.. memset(&r, 0, sizeof(r)); r.h.ah = 0x12; // EGA BIOS Get info, r.h.bl = 0x10; // Get info r.h.bh = 0xff; // Inpossible return value, dosxIntr(0x10, &r); // Call EGA BIOS, if(r.h.bh != 0xff) // EGA found? return TRUE; // Yes! } return FALSE; } /* * biosisMono() returns TRUE if the BIOS is currently in MONO mode. This * is the mode selected with the MODE co80 or MODE MONO command. For EGA and * VGA cards this mode doesn't tell a thing about the MONITOR attached!!! */ static boolean biosisMono(void) { union dosxReg r; //** Call the BIOS get video mode memset(&r, 0, sizeof(r)); r.w.ax = 0x0f00; dosxIntr(0x10, &r); r.h.al &= 0x7f; // Mask out DONT-CLEAR bit, if(r.h.al == 7) return TRUE; // Monochrome screen if(r.h.al == 2 || r.h.al == 3) return FALSE;// Color screen, return TRUE; // All else: return MONO } /* * getPrimaryType() returns the primary card type. */ static enum ePlScnType getPrimaryType() { if(biosisEGA()) // Minimal EGA? return biosisVGA() ? plsctVGA : plsctEGA; return biosisMono() ? plsctMono : plsctCGA; } /* * getType() determines the screen type. */ static void getType(void) { enum ePlScnType sct; sct = getPrimaryType(); // Get primary screen type; switch(sct) { default: plScnI.s_ismono = biosisMono(); break; case plsctVGA: plScnI.s_ismono = VgaMonoMonitor(); break; } //** Determine hardware addresses.. #if defined(__DJGPP__) plScnI.s_pbase = ScreenPrimary; #elif defined(__DOS4G__) plScnI.s_pbase = plScnI.s_ismono ? 0xb0000 : 0xb8000; #elif defined(__MSDOS__) plScnI.s_pseg = plScnI.s_ismono ? 0xb000 : 0xb800; #endif plScnI.s_iobase = plScnI.s_ismono ? 0x3b4 : 0x3d4; plScnI.s_type = sct; } /****************************************************************************/ /* */ /* CODING: Screen - Other base helper calls.. */ /* */ /****************************************************************************/ /* * getSize() inquires the BIOS about the screen size. */ static void getSize(void) { union dosxReg r; //** Get the current width of the screen, memset(&r, 0, sizeof(r)); r.w.ax = 0x0f00; // Get current video mode, dosxIntr(0x10, &r); // Video BIOS plScnI.s_wid = between(r.h.ah, 80, 256); if(plScnI.s_type < plsctEGA) // For all lower as EGA use 25 height plScnI.s_hig = 25; else { r.w.ax = 0x1130; // Get FONT information, r.w.bx = 0; dosxIntr(0x10, &r); r.h.dl += 1; // For some reason it reports 1 too small, plScnI.s_hig = between(r.h.dl, 25, 128); } } /* * getCurInfo() gets the current cursor info: position and shape, visibility. */ static void getCurInfo(void) { union dosxReg r; //** Ask the BIOS for the current cursor shape, memset(&r, 0, sizeof(r)); r.w.ax = 0x0300; // Get cursor shape, r.w.bx = 0; // Page 0 dosxIntr(0x10, &r); plScnI.s_cur_x = r.h.dl; plScnI.s_cur_y = r.h.dh; plScnI.s_curstart = r.h.ch; plScnI.s_curend = r.h.cl; if(! plScnI.s_curinit) // Cursor state not initialized? { plScnI.s_curon = TRUE; // Default to cursor ON, plScnI.s_curinit= TRUE; } } /* * plScnSetSize() sets the screen textmode to correspond to the specified * dimensions. note that it only actually supports standard DOS textmodes * 80x25, 80x43 and 80x50 */ void plScnSetSize(int xSize, int ySize) { union dosxReg r; // set text mode memset(&r, 0, sizeof(r)); r.w.ax = 0x0003; dosxIntr(0x10, &r); memset(&r, 0, sizeof(r)); if (xSize == 80 && ySize == 25) { // the previous int 10h call already set 80x25. do nothing here } else if (xSize == 80 && ySize == 43) { // TODO: doesn't work? what is the correct way to set 8x14 font? // i know my video card supports this as i can use 80x43 in other // applications ... will revisit this r.w.ax = 0x1122; dosxIntr(0x10, &r); } else if (xSize == 80 && ySize == 50) { r.w.ax = 0x1112; dosxIntr(0x10, &r); } //plScnI.s_inited = FALSE; getType(); getSize(); getCurInfo(); } /* * plScnInit() is called to get most of the info required to do screen I/O. * Depending on the "inited" flag it will get the current screen size, the * mode, cursor shape and visibility etc. */ static void plScnInit(void) { if(plScnI.s_inited) return; // Exit immediately if already inited, getType(); // ALWAYS get TYPE 1st! getSize(); // Get current mode (screen size) getCurInfo(); plScnI.s_inited = TRUE; // Don't init again. } /* * plScnSetFlash() is called to SET/CLEAR the flash/bright indicator. */ void plScnSetFlash(boolean on) { union dosxReg r; memset(&r, 0, sizeof(r)); r.w.ax = 0x1003; r.w.bx = on ? 1 : 0; // Set HILITE or FLASH mode. dosxIntr(0x10, &r); plScnI.s_isbright = !on; // Set ISBRIGHT mode flag. } #if defined(__DJGPP__) static void ScreenSetCursorShape(int shape) { __dpmi_regs reg; reg.h.ah = 0x01; reg.h.al = ScreenMode(); reg.x.cx = shape & 0x7f1f; __dpmi_int(0x10, ®); } #else /* * cardOut().. */ static void cardOut(int port, int val) { outp(plScnI.s_iobase, port); outp(plScnI.s_iobase + 1, val); } #endif /* * plScnCursorOn() switches the cursor ON or OFF. */ void plScnCursorOn(boolean on) { UWORD v; plScnInit(); plScnI.s_curon = on; v = (UWORD) ( ((plScnI.s_curstart & 0xff) << 8) | (plScnI.s_curend & 0xff)); if(! on) v |= 0x2000; // Disable if required.. #if defined(__DJGPP__) ScreenSetCursorShape(v); #else dosxDisable(); cardOut(10, v >> 8); cardOut(11, v & 0xff); if(! on) { cardOut(14, 20); cardOut(15, 0); } dosxEnable(); #endif } /* * plScnCursorShape() sets the cursor shape. */ void plScnCursorShape(int start, int end) { plScnInit(); plScnI.s_curstart = start; plScnI.s_curend = end; plScnCursorOn(plScnI.s_curon); // Switch cursor on/off; sets shape. } /* * plScnCursorShapeGet() */ void plScnCursorShapeGet(int* sp, int* ep) { getCurInfo(); *sp = plScnI.s_curstart; *ep = plScnI.s_curend; } /* * plScnCursorPos() sets the cursor's position. */ void plScnCursorPos(int x, int y) { #if defined(__DJGPP__) ScreenSetCursor(y,x); #else UWORD soff; plScnInit(); soff= (UWORD) (y * plScnI.s_wid + x); dosxDisable(); cardOut(14, (soff >> 8)); cardOut(15, soff & 0xff); dosxEnable(); plScnI.s_cur_x = x; plScnI.s_cur_y = y; #endif } /* * plScnCursorPosGet() */ void plScnCursorPosGet(int* xp, int* yp) { // getCurInfo(); *xp = plScnI.s_cur_x; *yp = plScnI.s_cur_y; } /****************************************************************************/ /* */ /* DJGPP implementation. */ /* */ /****************************************************************************/ #if defined(__DJGPP__) // Protected Mode void plScnWrite(unsigned x, unsigned y, unsigned short* buf, unsigned nch) { plScnInit(); movedata(_my_ds(), (unsigned) buf, _dos_ds, plScnI.s_pbase+(((y * plScnI.s_wid) + x)*2), nch*2); } void plScnRead(unsigned x, unsigned y, unsigned short* buf, unsigned nch) { plScnInit(); movedata(_dos_ds, plScnI.s_pbase+((y * plScnI.s_wid) + x)*2, _my_ds(), (unsigned) buf, nch*2); } static void moveVm(unsigned to, unsigned from, unsigned len) { movedata(_dos_ds, plScnI.s_pbase + from*2, _dos_ds, plScnI.s_pbase + to*2, len*2); } /****************************************************************************/ /* */ /* CODING: Dos4GW implementation.. */ /* */ /****************************************************************************/ #elif defined(__DOS4G__) void plScnWrite(unsigned x, unsigned y, unsigned short* buf, unsigned nch) { plScnInit(); memcpy((UBYTE*) plScnI.s_pbase+(((y * plScnI.s_wid) + x)*2), buf, nch<<1); } void plScnRead(unsigned x, unsigned y, unsigned short* buf, unsigned nch) { plScnInit(); memcpy(buf, (UBYTE*)plScnI.s_pbase+(((y * plScnI.s_wid) + x)*2), nch<<1); } static void moveVm(unsigned to, unsigned from, unsigned len) { memcpy((UBYTE*) plScnI.s_pbase+to*2, (UBYTE*) plScnI.s_pbase+from*2, len*2); } /****************************************************************************/ /* */ /* REAL MODE implementation. */ /* */ /****************************************************************************/ #elif defined(__MSDOS__) // REAL Mode #include void plScnWrite(unsigned x, unsigned y, unsigned short* buf, unsigned nch) { plScnInit(); memcpy(MK_FP(plScnI.s_pseg, ((y * plScnI.s_wid) + x)*2), buf, nch<<1); } void plScnRead(unsigned x, unsigned y, unsigned short* buf, unsigned nch) { plScnInit(); memcpy(buf, MK_FP(plScnI.s_pseg, ((y * plScnI.s_wid) + x)*2), nch<<1); } static void moveVm(unsigned to, unsigned from, unsigned len) { memcpy(MK_FP(plScnI.s_pseg, to*2), MK_FP(plScnI.s_pseg, from*2), len << 1); } #endif /****************************************************************************/ /* */ /* CODING: Screen - Shared Base functions. */ /* */ /****************************************************************************/ /* * plScnWidth() returns the width of the screen. */ int plScnWidth(void) { plScnInit(); return plScnI.s_wid; } /* * plScnHeight() returns the current height of the screen. */ int plScnHeight(void) { plScnInit(); return plScnI.s_hig; } /* * plScnType() returns the current screen type. */ enum ePlScnType plScnType(void) { plScnInit(); return plScnI.s_type; } /* * plScnIsMono() returns T if the screen is a MONO screen. */ boolean plScnIsMono(void) { plScnInit(); return plScnI.s_ismono; } /****************************************************************************/ /* */ /* CODING: Screen - Set and Scroll functions. */ /* */ /****************************************************************************/ #define BUFSZ 150 /* * plScnSetCell() */ void plScnSetCell(unsigned x, unsigned y, unsigned wid, unsigned hig, UWORD cell) { UWORD buf[BUFSZ], *p, *pend; unsigned len, lleft, px; //** Fill buffer, len = wid; if(len > BUFSZ) len = BUFSZ; p = buf; pend= p + len; while(p < pend) *p++ = cell; // Set as much as needed, //** For all lines, while(hig-- > 0) { //** For the current line, lleft = wid; px = x; while(lleft > 0) { len = lleft; // Determine #bytes from buf to use, if(len > BUFSZ) len = BUFSZ; plScnWrite(px, y, buf, len); px += len; lleft -= len; } y++; } } /* * plScnScrollUp() scrolls the region specified UP. */ void plScnScrollUp(int x, int y, int ex, int ey, int nlines, UWORD fill) { int from, to; //** Calculate the from and to offsets; to = y*plScnI.s_wid + x; // TO is top-of-window, from= to + nlines*plScnI.s_wid; // FROM is #lines further down, while(y < ey-nlines) { moveVm(to, from, (ex-x)); to += plScnI.s_wid; from+= plScnI.s_wid; y++; } plScnSetCell(x, y, (ex-x), nlines, fill); // Clear bottom. } /* * plScnScrollDown() scrolls the region DOWN. */ void plScnScrollDown(int x, int y, int ex, int ey, int nlines, UWORD fill) { int from, to, len; //** Scrolling down: move from bottom to top; to = ey * plScnI.s_wid + x; from= to - plScnI.s_wid*nlines; while(ey > y) { ey--; // Back one line; from -= plScnI.s_wid; to -= plScnI.s_wid; moveVm(to, from, (ex-x)); } plScnSetCell(x, y, (ex-x), nlines, fill); } /****************************************************************************/ /* */ /* CODING: Keyboard interface for DOS and DOS extender(s).. */ /* */ /****************************************************************************/ /* * Memo to self: I've changed the "get character" request code from the 00h * and 01h to 10h and 11h (extended keyboard). I should inquire the BIOS about * the availability of these calls, but preliminary tests show that most * BIOSes lie about the keyboard type, or do not implement the required * int15 calls proper. * Should work for most modern machines! */ /* * kbHasChar() returns T if a character is present in the keyboard buffer. It * is checked by comparing the keyboard queue ptrs in the bios segment. */ static boolean kbHasChar(void) { UWORD p1, p2; union dosxReg r; #if 0 // Switched off for extended kbd support. dosxMemRead(&p1, 0x0040001aul, 2); // Get 1st keybd pointer, dosxMemRead(&p2, 0x0040001cul, 2); // And 2nd, if(p1 == p2) return FALSE; // Exit if not ok; #endif //** Now ask if a real code is available by non-destructive qry of bios. memset(&r, 0, sizeof(r)); // Clear unused registers, r.w.ax = 0x1100; // !! Was 0x0100 dosxIntr(0x16, &r); // Call keyboard shit. if(r.w.flags & 0x40) return FALSE; // Z flag SET -> no data return TRUE; } /* * kbDosRead() does a destructive read by calling BIOS call 16H code 0. */ static boolean kbDosRead(struct plKbdInfo* ki) { union dosxReg r; UBYTE v; memset(&r, 0, sizeof(r)); // Make sure all segregs are 0 r.w.ax = 0x1000; // Was 0x0, now extended dosxIntr(0x16, &r); if((r.x.flags & 0x40) == 0) // Z flag NOT set? { ki->ki_scan = r.h.ah; ki->ki_ascii= r.h.al; dosxMemRead(&v, 0x00400017ul, 1); ki->ki_flags= (v & 0x03) ? PLKF_SHIFT : 0; if(v & 0x08) ki->ki_flags |= PLKF_ALT; if(v & 0x04) ki->ki_flags |= PLKF_CTRL; if(v & 0x10) ki->ki_flags |= PLKF_SCROLLLOCK; if(v & 0x20) ki->ki_flags |= PLKF_NUMLOCK; if(v & 0x40) ki->ki_flags |= PLKF_CAPSLOCK; return TRUE; } return FALSE; } /* * kbDosIdle() */ static void kbDosIdle(void) { union dosxReg r; memset(&r, 0, sizeof(r)); dosxIntr(0x28, &r); } /* * plKbdReadF() does a non-waiting read of the keyboard. */ boolean plKbdReadF(struct plKbdInfo* ki) { if(kbHasChar()) { if(kbDosRead(ki)) return TRUE; } kbDosIdle(); return FALSE; } /****************************************************************************/ /* */ /* CODING: Mouse - Dos MOUSE interface (Mou calls). */ /* */ /****************************************************************************/ /*--------------------------------------------------------------------------*/ /* DEFINES: Mouse command codes. */ /*--------------------------------------------------------------------------*/ #define MC_RESET 0x0000 #define MC_CURSEN 0x0001 /* Enable cursor position */ #define MC_CURSDI 0x0002 /* Disable cursor */ #define MC_GETCUR 0x0003 /* Get cursor position */ #define MC_SETCUR 0x0004 /* Set cursor position */ #define MC_GETBPRESS 0x0005 /* Get button press state */ #define MC_GETBRELEASE 0x0006 /* Button release state */ #define MC_SETXRANGE 0x0007 /* Set X cursor range */ #define MC_SETYRANGE 0x0008 /* Set Y cursor range */ #define MC_GRCURSOR 0x0009 /* Set Graphic cursor style */ #define MC_TXCURSOR 0x000a /* Set text mode cursor style */ #define MC_GETMOTION 0x000b /* Get mouse motion # */ #define MC_SETEVENT 0x000c /* DefiNE event handler location */ #define MC_LPENABLE 0x000d /* Enable light pen emulation */ #define MC_LPDISABLE 0x000e /* Disable light pen emulation */ #define MC_SETSENS 0x000f /* Set sensitivity (mousemove/pixel) */ #define MC_CDRANGE 0x0010 /* Disable cursor in given range */ #define MC_DBLSPEEDTH 0x0013 /* DefiNE double-speed treshold */ static ULONG MouseCursorState; /* Mouse saved cursor state */ static boolean MousePresent; // T if mouse was located at init. static ULONG MousePressCount; // #times the mouse was clicked. /* * MOUSIsPresent() returns T if the mouse is present. It can be called only * when the MOUSInit call has been done. */ boolean MOUSIsPresent(void) { return MousePresent; } /* * MOUSPressCount() */ ULONG MOUSPressCount(void) { return MousePressCount; } /* * MOUSInit() initializes the mouse driver. It returns FALSE if no mouse's * present. When it's not called by the user program no mouse support * is given.. */ boolean MOUSInit(void) { // UBYTE *p; union dosxReg r; if(! MousePresent) /* If not already called */ { #if 0 // No vector for EXTENDERS /**** Get the contents of interrupt 33H ****/ p = (UBYTE *)getvect(0x33); if(p == NULL || *p == 0xcf) return FALSE; #endif /**** Mouse driver present: Call the mouse driver ****/ memset(&r, 0, sizeof(r)); r.w.ax = MC_RESET; dosxIntr(0x33, &r); if(r.w.ax != 0) /* Mouse attached? */ { MousePresent = TRUE; MOUSSetTextCursor(0, 0); /* Use default text cursor */ } MouseCursorState= 0; /* Cursor invisible */ } else assert(0); return MousePresent; /* Return mouse state */ } /* * MOUSExit() doesn't do a thing but is called to maintain compatibility. */ void MOUSExit(void) { MousePresent = FALSE; MouseCursorState= 0; } /* * MOUSCursen() enables/disables the mouse cursor. It takes notice of the * previous state and calls the routine ONLY if the state needs a change. */ void MOUSCursen(boolean enable) { union dosxReg r; if(MousePresent) { if( (enable && !(MouseCursorState & 1)) || (!enable && (MouseCursorState & 1))) { memset(&r, 0, sizeof(r)); r.w.ax = enable ? MC_CURSEN : MC_CURSDI; dosxIntr(0x33, &r); if(enable) MouseCursorState |= 1; else MouseCursorState &= ~1; } } } /* * MOUSSaveCurs() saves the current cursor state. */ void MOUSSaveCurs(void) { ULONG state; state = MouseCursorState & 1; MouseCursorState = (MouseCursorState << 1) | state; } /* * MOUSRestCurs() restores the last cursor state. */ void MOUSRestCurs(void) { ULONG nstate; nstate = MouseCursorState >> 1; // Get new state of cursor, MOUSCursen((boolean) (nstate & 1) ); // Make mouse's new state, MouseCursorState = nstate; // And set the new state. } /* * MOUSPos() returns the current mouse position and the button states. */ void MOUSPos(UWORD *x, UWORD *y, boolean *leftbutton, boolean *rightbutton) { union dosxReg r; if(MousePresent) { memset(&r, 0, sizeof(r)); r.w.ax = MC_GETCUR; dosxIntr(0x33, &r); if(leftbutton != NULL) *leftbutton = (r.w.bx & 1) != 0; if(rightbutton != NULL) *rightbutton = (r.w.bx & 2) != 0; if(x != NULL) *x = r.w.cx; if(y != NULL) *y = r.w.dx; } } /* * MOUSSetpos() sets a new mouse cursor position */ void MOUSSetpos(UWORD x, UWORD y) { union dosxReg r; if(MousePresent) { r.w.ax = MC_SETCUR; r.w.cx = x; r.w.dx = y; dosxIntr(0x33, &r); } } /* * MOUSSetTextCursor() sets the text cursor style. It always selects a * software cursor and, if both screenmask and cursormask are zero it * selects an inverse 'o' (0x09) as cursor character. */ void MOUSSetTextCursor(UWORD screenmask, UWORD cursormask) { union dosxReg r; if(MousePresent) { memset(&r, 0, sizeof(r)); r.w.ax = MC_TXCURSOR; /* Define text cursor command */ r.w.bx = 0; /* Software text cursor */ if(screenmask == 0 && cursormask == 0) { #if 0 r.w.cx = 0x0000; /* Screen mask value: all bits OFF */ r.w.dx = 0x1f09; /* Cursor mask: an 'o' */ #endif r.w.cx = 0x7700; /* Screen mask value */ r.w.dx = 0x77fe; /* Cursor: a blob */ } else { r.w.cx = screenmask; r.w.dx = cursormask; } dosxIntr(0x33, &r); } } /* * MOUSPressed() returns TRUE when the mouse key was pressed AND: * a. The mouse key has been released since the last call OR * b. The mouse position has changed. * It returns the new mouse coordinates in character positions. */ boolean MOUSPressed(UWORD *x, UWORD *y) { boolean leftbutton; static boolean waspressed; static UWORD lx, ly; if(MousePresent) { MOUSPos(x, y, &leftbutton, NULL); /* Get current mouse pos & state */ *x /= 8; /* Scale to characters */ *y /= 8; /* Idem */ if(leftbutton) /* Key pressed? */ { /**** Key was pressed! Have the coords changed since the last ****/ /**** time? ****/ if(*x == lx && *y == ly && waspressed) return FALSE; /* Nothing changed */ lx = *x; ly = *y; waspressed= TRUE; return TRUE; } else waspressed = FALSE; } return FALSE; } /* * MOUSSetBounds() attempts to automatically set appropriate mouse cursor * boundaries based on the current screen textmode. * NOTE: This is currently written assuming 80 column text modes, with * the only possible screen heights being 25, 43 or 80. */ boolean MOUSSetBounds(void) { union dosxReg r; int rows; int height; rows = plScnHeight(); if (rows == 43) { height = 350; } else if (rows == 50) { height = 400; } else { height = 200; } if(MousePresent) { memset(&r, 0, sizeof(r)); r.w.ax = MC_SETXRANGE; r.w.cx = 0; r.w.dx = 639; dosxIntr(0x33, &r); memset(&r, 0, sizeof(r)); r.w.ax = MC_SETYRANGE; r.w.cx = 0; r.w.dx = (height - 1); dosxIntr(0x33, &r); return TRUE; } return FALSE; } #endif // DOS || DOSP32