home *** CD-ROM | disk | FTP | other *** search
- /**
- ** MOUSE.C
- **
- ** Copyright (C) 1992, Csaba Biegl
- ** 820 Stirrup Dr, Nashville, TN, 37221
- ** csaba@vuse.vanderbilt.edu
- **
- ** This file is distributed under the terms listed in the document
- ** "copying.cb", available from the author at the address above.
- ** A copy of "copying.cb" should accompany this file; if not, a copy
- ** should be available from where this file was obtained. This file
- ** may not be distributed without a verbatim copy of "copying.cb".
- ** You should also have received a copy of the GNU General Public
- ** License along with this program (it is in the file "copying");
- ** if not, write to the Free Software Foundation, Inc., 675 Mass Ave,
- ** Cambridge, MA 02139, USA.
- **
- ** This program 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 General Public License for more details.
- **/
-
- #include "grx.h"
- #include "mousex.h"
- #include "libgrx.h"
- #include "interrup.h"
- #include "clipping.h"
-
- #include "../events/eventque.h"
- #include <string.h>
- #include <stdarg.h>
-
- #ifdef __TURBOC__
- # include <time.h>
- # include <conio.h>
- #endif
-
- #ifdef __GNUC__
- extern long rawclock();
- # define clock() rawclock()
- #endif
-
- /*
- * mouse status flags
- */
- #define UNKNOWN 0
- #define MISSING 1
- #define PRESENT 2
- #define INITTED 3
- #define QUEUED 4
-
- #define DRAW_STACK 1024
- #define QUEUE_SIZE 100
-
- #define CHECK_CONTEXT(cxt) ((cxt)->gc_baseaddr == SCREEN->gc_baseaddr)
-
- extern GrCursor *_GrMouseCursor; /* current mouse cursor */
-
- static EventQueue *queue,qbuf;
- static int mouse_status = UNKNOWN;
- static int own_cursor = FALSE;
- static int use_queue = FALSE;
- static int kb_enable = TRUE;
- static int ms_enable = TRUE;
- static int ms_curmode = M_CUR_NORMAL;
- static int ms_xanchor,ms_yanchor;
- static int ms_dx2,ms_dy2;
- static int ms_curcolor;
- static int ms_buttons;
- static int ms_xpos;
- static int ms_ypos;
-
- #define ms_dx1 ms_xanchor
- #define ms_dy1 ms_yanchor
-
- static void (*getevent)(int flags,MouseEvent *event);
-
- static char ptr12x16bits[] = {
- 0,1,0,0,0,0,0,0,0,0,0,0,
- 1,2,1,0,0,0,0,0,0,0,0,0,
- 1,2,2,1,0,0,0,0,0,0,0,0,
- 1,2,2,2,1,0,0,0,0,0,0,0,
- 1,2,2,2,2,1,0,0,0,0,0,0,
- 1,2,2,2,2,2,1,0,0,0,0,0,
- 1,2,2,2,2,2,2,1,0,0,0,0,
- 1,2,2,2,2,2,2,2,1,0,0,0,
- 1,2,2,2,2,2,2,2,2,1,0,0,
- 1,2,2,2,2,2,2,2,2,2,1,0,
- 1,2,2,2,2,2,2,2,2,2,2,1,
- 1,2,2,2,2,1,1,1,1,1,1,0,
- 1,2,2,2,1,0,0,0,0,0,0,0,
- 1,2,2,1,0,0,0,0,0,0,0,0,
- 1,2,1,0,0,0,0,0,0,0,0,0,
- 0,1,0,0,0,0,0,0,0,0,0,0,
- };
-
- static int check_mouse(void)
- {
- if(mouse_status < INITTED) {
- if(mouse_status != MISSING) MouseInit();
- if(mouse_status < INITTED) return(FALSE);
- }
- return(TRUE);
- }
-
- static void draw_special(void)
- {
- int x = _GrMouseCursor->cr_xcord;
- int y = _GrMouseCursor->cr_ycord;
- int msflag = _GrMouseCheck;
- GrContext csave;
-
- csave = *CURC;
- *CURC = *SCREEN;
- _GrMouseCheck = FALSE;
- switch(ms_curmode) {
- case M_CUR_RUBBER:
- GrBox(x,y,ms_xanchor,ms_yanchor,ms_curcolor);
- break;
- case M_CUR_LINE:
- GrLine(x,y,ms_xanchor,ms_yanchor,ms_curcolor);
- break;
- case M_CUR_BOX:
- GrBox(x+ms_dx1,y+ms_dy1,x+ms_dx2,y+ms_dy2,ms_curcolor);
- break;
- }
- *CURC = csave;
- _GrMouseCheck = msflag;
- }
-
- static void draw_mouse(void)
- {
- if(_GrMouseCursor->cr_displayed) return;
- GrMoveCursor(_GrMouseCursor,queue->evq_xpos,queue->evq_ypos);
- GrDisplayCursor(_GrMouseCursor);
- if(ms_curmode != M_CUR_NORMAL) draw_special();
- }
-
- static void erase_mouse(void)
- {
- if(!_GrMouseCursor->cr_displayed) return;
- if(ms_curmode != M_CUR_NORMAL) draw_special();
- GrEraseCursor(_GrMouseCursor);
- }
-
- static void move_mouse(void)
- {
- #ifdef CRASH_AT_0_0
- if((queue->evq_xpos == 0) && (queue->evq_ypos == 0)) {
- char tmp[20];
- char *ptr = (char *)NULL;
- int crashval = ++(*ptr);
- sprintf(tmp,"%d",crashval);
- }
- #endif
- if(!_GrMouseCursor->cr_displayed) {
- GrMoveCursor(_GrMouseCursor,queue->evq_xpos,queue->evq_ypos);
- return;
- }
- if(ms_curmode != M_CUR_NORMAL) draw_special();
- GrMoveCursor(_GrMouseCursor,queue->evq_xpos,queue->evq_ypos);
- if(ms_curmode != M_CUR_NORMAL) draw_special();
- }
-
- static void get_polled_event(int flags,MouseEvent *e)
- {
- REGISTERS regs;
- int moved;
- int diff;
-
- for( ; ; ) {
- if((flags & M_KEYPRESS) && kbhit()) {
- e->flags = M_KEYPRESS;
- e->key = getkey();
- e->kbstat = getkbstat();
- e->time = clock();
- return;
- }
- moved = 0;
- regs.r_ax = 11;
- int33(®s);
- if((diff = (short)regs.r_cx) != 0) {
- ms_xpos += diff;
- if((diff = ms_xpos / queue->evq_xspeed) != 0) {
- ms_xpos %= queue->evq_xspeed;
- if(IABS(diff) >= queue->evq_thresh)
- diff *= queue->evq_accel;
- diff += queue->evq_xpos;
- if(diff <= queue->evq_xmin) diff = queue->evq_xmin;
- if(diff >= queue->evq_xmax) diff = queue->evq_xmax;
- if(diff != queue->evq_xpos) {
- queue->evq_xpos = diff;
- queue->evq_moved = 1;
- moved = M_MOTION;
- }
- }
- }
- if((diff = (short)regs.r_dx) != 0) {
- ms_ypos += diff;
- if((diff = ms_ypos / queue->evq_yspeed) != 0) {
- ms_ypos %= queue->evq_yspeed;
- if(IABS(diff) >= queue->evq_thresh)
- diff *= queue->evq_accel;
- diff += queue->evq_ypos;
- if(diff <= queue->evq_ymin) diff = queue->evq_ymin;
- if(diff >= queue->evq_ymax) diff = queue->evq_ymax;
- if(diff != queue->evq_ypos) {
- queue->evq_ypos = diff;
- queue->evq_moved = 1;
- moved = M_MOTION;
- }
- }
- }
- if(moved && queue->evq_drawmouse) move_mouse();
- regs.r_ax = 3;
- int33(®s);
- if(flags & M_BUTTON_DOWN) {
- diff = (regs.r_bx & ~ms_buttons);
- if(diff & M_LEFT) moved |= M_LEFT_DOWN;
- if(diff & M_MIDDLE) moved |= M_MIDDLE_DOWN;
- if(diff & M_RIGHT) moved |= M_RIGHT_DOWN;
- }
- if(flags & M_BUTTON_UP) {
- diff = (~regs.r_bx & ms_buttons);
- if(diff & M_LEFT) moved |= M_LEFT_UP;
- if(diff & M_MIDDLE) moved |= M_MIDDLE_UP;
- if(diff & M_RIGHT) moved |= M_RIGHT_UP;
- }
- ms_buttons = regs.r_bx & (M_LEFT | M_MIDDLE | M_RIGHT);
- if(flags & (moved | M_POLL)) {
- e->flags = moved & flags;
- e->x = queue->evq_xpos;
- e->y = queue->evq_ypos;
- e->buttons = ms_buttons;
- e->kbstat = getkbstat();
- e->time = clock();
- return;
- }
- }
- }
-
- static void get_queued_event(int flags,MouseEvent *e)
- {
- EventRecord evr;
- int moved = 0;
-
- for( ; ; ) {
- if(queue->evq_moved) {
- moved = M_MOTION;
- queue->evq_moved = 0;
- }
- if(EventQueueNextEvent(queue,&evr)) {
- switch(evr.evt_type) {
- case EVENT_KEYBD:
- if(flags & M_KEYPRESS) {
- e->flags = M_KEYPRESS;
- e->key = evr.evt_keycode;
- e->kbstat = evr.evt_kbstat;
- e->time = evr.evt_time;
- return;
- }
- break;
- case EVENT_MOUSE:
- ms_buttons = evr.evt_button;
- if(flags & evr.evt_mask) {
- e->flags = flags & (evr.evt_mask | moved);
- e->x = evr.evt_xpos;
- e->y = evr.evt_ypos;
- e->buttons = evr.evt_button;
- e->kbstat = evr.evt_kbstat;
- e->time = evr.evt_time;
- return;
- }
- break;
- }
- continue;
- }
- if(flags & (moved | M_POLL)) {
- e->flags = flags & moved;
- e->x = queue->evq_xpos;
- e->y = queue->evq_ypos;
- e->buttons = ms_buttons;
- e->kbstat = getkbstat();
- e->time = clock();
- return;
- }
- }
- }
-
- void MouseEventMode(int use_interrupts)
- {
- use_queue = use_interrupts;
- }
-
- int MouseDetect(void)
- {
- REGISTERS regs;
-
- if(mouse_status == UNKNOWN) {
- regs.r_ax = 0;
- int33(®s);
- mouse_status = (regs.r_ax == 0) ? MISSING : PRESENT;
- }
- return((mouse_status == MISSING) ? FALSE : TRUE);
- }
-
- void MouseUnInit(void)
- {
- REGISTERS regs;
-
- if(mouse_status >= INITTED) {
- if(mouse_status == QUEUED) {
- EventQueueDeInit();
- queue = NULL;
- }
- else {
- regs.r_ax = 0;
- int33(®s);
- }
- if(_GrMouseDrawn) erase_mouse();
- mouse_status = PRESENT;
- }
- }
-
- void MouseInit(void)
- {
- REGISTERS regs;
-
- if(mouse_status != PRESENT) {
- MouseDetect();
- MouseUnInit();
- if(mouse_status != PRESENT) return;
- }
- if(use_queue) {
- queue = EventQueueInit(QUEUE_SIZE,DRAW_STACK,move_mouse);
- if(queue != NULL) {
- mouse_status = QUEUED;
- getevent = get_queued_event;
- queue->evq_drawmouse = FALSE;
- }
- }
- if(mouse_status < INITTED) {
- queue = &qbuf;
- regs.r_ax = 0;
- int33(®s);
- regs.r_ax = 3;
- int33(®s);
- ms_buttons = regs.r_bx & (M_LEFT | M_MIDDLE | M_RIGHT);
- regs.r_ax = 11;
- int33(®s);
- ms_xpos = 0;
- ms_ypos = 0;
- getevent = get_polled_event;
- mouse_status = INITTED;
- }
- if(_GrMouseCursor == NULL) MouseSetColors(GrWhite(),GrBlack());
- _GrMouseBlock = MouseBlock;
- _GrMouseUnBlock = MouseUnBlock;
- _GrMouseUnInit = MouseUnInit;
- _GrMouseDrawn = FALSE;
- _GrMouseCheck = FALSE;
- MouseEventEnable(kb_enable,ms_enable);
- MouseSetLimits(0,0,(_GrScreenX - 1),(_GrScreenY - 1));
- MouseWarp((_GrScreenX >> 1),(_GrScreenY >> 1));
- MouseSetSpeed(1);
- MouseSetAccel(1000,1);
- }
-
- void MouseSetSpeed(int speed)
- {
- if(!check_mouse()) return;
- queue->evq_xspeed = speed;
- queue->evq_yspeed = speed;
- }
-
- void MouseSetAccel(int thresh,int accel)
- {
- if(!check_mouse()) return;
- queue->evq_thresh = thresh;
- queue->evq_accel = accel;
- }
-
- void MouseSetLimits(int x1,int y1,int x2,int y2)
- {
- if(!check_mouse()) return;
- CLIPBOXTOCONTEXT(SCREEN,x1,y1,x2,y2);
- queue->evq_xmin = x1;
- queue->evq_ymin = y1;
- queue->evq_xmax = x2;
- queue->evq_ymax = y2;
- MouseWarp(queue->evq_xpos,queue->evq_ypos);
- }
-
- void MouseGetLimits(int *x1,int *y1,int *x2,int *y2)
- {
- if(!check_mouse()) return;
- *x1 = queue->evq_xmin;
- *y1 = queue->evq_ymin;
- *x2 = queue->evq_xmax;
- *y2 = queue->evq_ymax;
- }
-
- void MouseWarp(int x,int y)
- {
- char msdraw;
-
- if(!check_mouse()) return;
- msdraw = queue->evq_drawmouse;
- queue->evq_drawmouse = FALSE;
- if(x < queue->evq_xmin) x = queue->evq_xmin;
- if(y < queue->evq_ymin) y = queue->evq_ymin;
- if(x > queue->evq_xmax) x = queue->evq_xmax;
- if(y > queue->evq_ymax) y = queue->evq_ymax;
- queue->evq_xpos = x;
- queue->evq_ypos = y;
- if(_GrMouseDrawn) move_mouse();
- queue->evq_drawmouse = msdraw;
- }
-
- void MouseSetCursor(GrCursor *cursor)
- {
- GrCursor *old = _GrMouseCursor;
- char msdraw = 0;
-
- if(cursor != NULL) {
- if(mouse_status >= INITTED) {
- msdraw = queue->evq_drawmouse;
- queue->evq_drawmouse = FALSE;
- if(_GrMouseDrawn) erase_mouse();
- }
- _GrMouseCursor = cursor;
- if(own_cursor) GrDestroyCursor(old);
- own_cursor = FALSE;
- if(mouse_status >= INITTED) {
- if(_GrMouseDrawn) draw_mouse();
- queue->evq_drawmouse = msdraw;
- }
- }
- }
-
- void MouseSetColors(int fg,int bg)
- {
- GrCursor *new;
- int cols[3];
-
- cols[0] = 2;
- cols[1] = bg;
- cols[2] = fg;
- new = GrBuildCursor(ptr12x16bits,12,16,1,1,cols);
- if(new != NULL) {
- MouseSetCursor(new);
- own_cursor = TRUE;
- }
- }
-
- void MouseSetCursorMode(int mode,...)
- {
- va_list ap;
- char msdraw = 0;
-
- if(mouse_status >= INITTED) {
- msdraw = queue->evq_drawmouse;
- queue->evq_drawmouse = FALSE;
- if(_GrMouseDrawn && (ms_curmode != M_CUR_NORMAL)) draw_special();
- }
- va_start(ap,mode);
- switch(mode) {
- case M_CUR_RUBBER:
- ms_curmode = M_CUR_RUBBER;
- ms_xanchor = va_arg(ap,int);
- ms_yanchor = va_arg(ap,int);
- ms_curcolor = (va_arg(ap,int) & C_COLOR) | GrXOR;
- break;
- case M_CUR_LINE:
- ms_curmode = M_CUR_LINE;
- ms_xanchor = va_arg(ap,int);
- ms_yanchor = va_arg(ap,int);
- ms_curcolor = (va_arg(ap,int) & C_COLOR) | GrXOR;
- break;
- case M_CUR_BOX:
- ms_curmode = M_CUR_BOX;
- ms_dx1 = va_arg(ap,int);
- ms_dy1 = va_arg(ap,int);
- ms_dx2 = va_arg(ap,int);
- ms_dy2 = va_arg(ap,int);
- ms_curcolor = (va_arg(ap,int) & C_COLOR) | GrXOR;
- break;
- default:
- ms_curmode = M_CUR_NORMAL;
- break;
- }
- va_end(ap);
- if(mouse_status >= INITTED) {
- if(_GrMouseDrawn && (ms_curmode != M_CUR_NORMAL)) draw_special();
- queue->evq_drawmouse = msdraw;
- }
- }
-
- GrCursor *MouseGetCursor(void)
- {
- return(_GrMouseCursor);
- }
-
- int MouseCursorIsDisplayed(void)
- {
- return(_GrMouseDrawn);
- }
-
- void MouseDisplayCursor(void)
- {
- if((mouse_status < INITTED) || _GrMouseDrawn) return;
- draw_mouse();
- _GrMouseDrawn = TRUE;
- _GrMouseCheck = CHECK_CONTEXT(CURC) ? TRUE : FALSE;
- queue->evq_drawmouse = TRUE;
- }
-
- void MouseEraseCursor(void)
- {
- if((mouse_status < INITTED) || !_GrMouseDrawn) return;
- queue->evq_drawmouse = FALSE;
- _GrMouseDrawn = FALSE;
- _GrMouseCheck = FALSE;
- erase_mouse();
- }
-
- int MouseBlock(GrContext *c,int x1,int y1,int x2,int y2)
- {
- int mx1,my1,mx2,my2;
-
- if(c == NULL) c = CURC;
- if((mouse_status < INITTED) || !_GrMouseDrawn || !CHECK_CONTEXT(c))
- return(FALSE);
- queue->evq_drawmouse = FALSE;
- queue->evq_moved = FALSE;
- x1 += c->gc_xoffset; y1 += c->gc_yoffset;
- x2 += c->gc_xoffset; y2 += c->gc_yoffset;
- mx1 = _GrMouseCursor->cr_xwpos;
- my1 = _GrMouseCursor->cr_ywpos;
- mx2 = mx1 + _GrMouseCursor->cr_xwork - 1;
- my2 = my1 + _GrMouseCursor->cr_ywork - 1;
- if(ms_curmode != M_CUR_NORMAL) {
- int cx2,cy2;
- int cx1 = _GrMouseCursor->cr_xcord;
- int cy1 = _GrMouseCursor->cr_ycord;
- switch(ms_curmode) {
- case M_CUR_RUBBER:
- cx2 = ms_xanchor;
- cy2 = ms_yanchor;
- break;
- case M_CUR_LINE:
- cx2 = ms_xanchor;
- cy2 = ms_yanchor;
- break;
- case M_CUR_BOX:
- cx2 = cx1 + ms_dx2;
- cy2 = cy1 + ms_dy2;
- cx1 += ms_dx1;
- cy2 += ms_dy1;
- break;
- default:
- return(FALSE);
- }
- SORT2(cx1,cx2);
- SORT2(cy1,cy2);
- if(cx1 < mx1) mx1 = cx1;
- if(cy1 < my1) my1 = cy1;
- if(cx2 > mx2) mx2 = cx2;
- if(cy2 > my2) my2 = cy2;
- }
- if(mx1 > x1) x1 = mx1;
- if(my1 > y1) y1 = my1;
- if(mx2 < x2) x2 = mx2;
- if(my2 < y2) y2 = my2;
- if((x1 <= x2) && (y1 <= y2)) {
- _GrMouseDrawn = FALSE;
- erase_mouse();
- }
- _GrMouseCheck = FALSE;
- return(TRUE);
- }
-
- void MouseUnBlock(void)
- {
- if(mouse_status < INITTED) return;
- if(queue->evq_moved) move_mouse();
- if(!_GrMouseDrawn) draw_mouse();
- _GrMouseDrawn = TRUE;
- _GrMouseCheck = CHECK_CONTEXT(CURC) ? TRUE : FALSE;
- queue->evq_drawmouse = TRUE;
- }
-
- void MouseEventEnable(int enable_kb,int enable_ms)
- {
- if(mouse_status >= INITTED) {
- queue->evq_enable =
- (enable_kb ? EVENT_ENABLE(EVENT_KEYBD) : 0) |
- (enable_ms ? EVENT_ENABLE(EVENT_MOUSE) : 0);
- }
- kb_enable = enable_kb;
- ms_enable = enable_ms;
- }
-
- void MouseGetEvent(int flags,MouseEvent *e)
- {
- int erase = FALSE;
-
- if(!kb_enable) flags &= ~M_KEYPRESS;
- if(!ms_enable) flags &= ~(M_MOTION | M_BUTTON_DOWN | M_BUTTON_UP);
- if(!(flags & M_EVENT)) { e->flags = 0; return; }
- if(!check_mouse()) {
- e->flags = 0;
- if((flags & M_KEYPRESS) && (!(flags & M_POLL) || kbhit())) {
- e->flags = M_KEYPRESS;
- e->key = getkey();
- e->kbstat = getkbstat();
- e->time = clock();
- }
- return;
- }
- if(!_GrMouseDrawn && !(flags & M_NOPAINT)) {
- draw_mouse();
- queue->evq_drawmouse = TRUE;
- erase = TRUE;
- }
- (*getevent)(flags,e);
- if(erase) {
- queue->evq_drawmouse = FALSE;
- erase_mouse();
- }
- }
-
- int MousePendingEvent(void)
- {
- if((mouse_status >= INITTED) && (queue->evq_cursize > 0))
- return(TRUE);
- return(FALSE);
- }
-