/* GEMGRLIB.C 4/11/84 - 01/07/85 Gregg Morris */ /* Reg Opt 03/08/85 - 04/26/85 Derek Mui */ /* Restore back into C language from Version 3.01 8/29/90 D.Mui */ /* Save the current mouse form and add mouse reset 5/8/91 D.Mui */ /* Modified gr_mouse 6/14/91 D.Mui */ /* Convert to Lattice C 5.51 2/17/93 C.Gee */ /* Force the use of prototypes 2/24/93 C.Gee */ /* ----------------------------------------------------------- * AES Version 4.0 MultiTOS version is written by Derek M. Mui * Copyright (C) 1992 * Atari (U.S.) Corp * All Rights Reserved * ----------------------------------------------------------- */ /* * ------------------------------------------------------------- * GEM Application Environment Services Version 1.1 * Serial No. XXXX-0000-654321 All Rights Reserved * Copyright (C) 1985 Digital Research Inc. * ------------------------------------------------------------- */ #include "pgem.h" #include "pmisc.h" #include "machine.h" #include "dispvars.h" #include "rslib.h" #include "mintbind.h" #include "gemusa.h" EXTERN WORD gl_mouse; EXTERN WORD gl_moff; EXTERN LONG ad_hgmice; EXTERN LONG ad_armice; EXTERN WORD cu_button; EXTERN GRECT gl_rscreen; EXTERN GRECT gl_rzero; EXTERN LONG ad_sysglo; EXTERN WORD gl_button, kstate; GLOBAL UWORD gl_mkind; /* current mouse kind */ GLOBAL WORD gl_omkind; /* old mouse kind */ GLOBAL MFORM gl_cmform; /* current aes mouse form */ GLOBAL MFORM gl_omform; /* old aes mouse form */ GLOBAL WORD gl_mfid; /* current mouse form owner id */ GLOBAL WORD gl_omfid; /* previous mouse owner id */ /* * Routine to watch the mouse while the button is down and * it stays inside/outside of the specified rectangle. * Return TRUE as long as the mouse is down. Block until the * mouse moves into or out of the specified rectangle. */ WORD gr_stilldn(out, x, y, w, h) WORD out, x, y, w, h; { WORD status; /* compiler had better put the values out, */ /* x, y, w, h in the right order on the */ /* stack to form a MOBLK */ while( TRUE ) { forker(); if ( !( cu_button & 0x01 ) ) { status = FALSE; break; } else { if ( ev_mchk( ( MOBLK *)&out ) ) { status = TRUE; break; } } } return( status ); } /* gr_stilldn */ VOID gr_setup(color) WORD color; { gsx_sclip(&gl_rscreen); gsx_attr(FALSE, MD_XOR, color); } VOID gr_clamp(xorigin, yorigin, wmin, hmin, pneww, pnewh) WORD xorigin, yorigin; WORD wmin, hmin; WORD *pneww, *pnewh; { WORD mx, my; gsx_mxmy(&mx, &my); *pneww = max(mx - xorigin + 1, wmin); *pnewh = max(my - yorigin + 1, hmin); } VOID gr_scale(xdist, ydist, pcnt, pxstep, pystep) REG WORD xdist, ydist; WORD *pcnt; REG WORD *pxstep, *pystep; { REG WORD i; REG WORD dist; gr_setup(BLACK); dist = (xdist + ydist) / 2; for(i=0; dist; i++) dist /= 2; if (*pcnt = i) { *pxstep = max(1, xdist / i); *pystep = max(1, ydist / i); } else *pxstep = *pystep = 1; } VOID gr_stepcalc(orgw, orgh, pt, pcx, pcy, pcnt, pxstep, pystep) WORD orgw, orgh; REG GRECT *pt; REG WORD *pcx, *pcy; WORD *pcnt, *pxstep, *pystep; { *pcx = (pt->g_w/2) - (orgw/2); *pcy = (pt->g_h/2) - (orgh/2); gr_scale(*pcx, *pcy, pcnt, pxstep, pystep); *pcx += pt->g_x; *pcy += pt->g_y; } VOID gr_xor(clipped, cnt, cx, cy, cw, ch, xstep, ystep, dowdht) WORD clipped; WORD cnt; WORD cx, cy, cw, ch; REG WORD xstep, ystep; WORD dowdht; { GRECT crect; crect.g_x = cx; crect.g_y = cy; crect.g_w = cw; crect.g_h = ch; do { if (clipped) gsx_xcbox( &crect ); else gsx_xbox( &crect ); crect.g_x -= xstep; crect.g_y -= ystep; if (dowdht) { crect.g_w += (2 * xstep); crect.g_h += (2 * ystep); } } while (cnt--); } VOID gr_draw(have2box, po, poff) WORD have2box; REG GRECT *po; REG GRECT *poff; { GRECT t; gsx_xbox(po); if (have2box) { r_set( ( WORD *)&t, po->g_x + poff->g_x, po->g_y + poff->g_y, po->g_w + poff->g_w, po->g_h + poff->g_h ); gsx_xbox(&t); } } WORD gr_wait(po, poff, mx, my) REG GRECT *po; REG GRECT *poff; WORD mx, my; { REG WORD have2box; REG WORD down; have2box = !rc_equal( ( WORD *)&gl_rzero, ( WORD *)poff); /* draw old */ gsx_moff(); gr_draw(have2box, po, poff); gsx_mon(); /* wait for change */ down = gr_stilldn(TRUE, mx, my, 1, 1); /* erase old */ gsx_moff(); gr_draw(have2box, po, poff); gsx_mon(); /* return exit event */ return(down); } /* * Stretch the free corner of an XOR box(w,h) that is pinned at * another corner based on mouse movement until the button comes * up. Also draw a second box offset from the stretching box. */ VOID gr_rubwind(xorigin, yorigin, wmin, hmin, poff, pwend, phend) WORD xorigin, yorigin; WORD wmin, hmin; GRECT *poff; WORD *pwend, *phend; { /* WORD have2box;*/ WORD down; GRECT o; wm_update(3); gr_setup(BLACK); r_set( ( WORD *)&o, xorigin, yorigin, 0, 0); /* clamp size of rubber */ /* box to no smaller */ /* than wmin, hmin */ do { gr_clamp(o.g_x, o.g_y, wmin, hmin, &o.g_w, &o.g_h); down = gr_wait(&o, poff, o.g_x+o.g_w-1, o.g_y+o.g_h-1); } while (down); *pwend = o.g_w; *phend = o.g_h; wm_update(2); } /* gr_rubwind */ /* * Stretch the free corner of a XOR box(w,h) that is pinned at * another corner based on mouse movement until the button comes * up. This is also called a rubber-band box. */ VOID gr_rubbox(xorigin, yorigin, wmin, hmin, pwend, phend) WORD xorigin, yorigin; WORD wmin, hmin; WORD *pwend, *phend; { wm_update( 3 ); gr_rubwind(xorigin, yorigin, wmin, hmin, &gl_rzero, pwend, phend); wm_update( 2 ); } /* * Drag a moving XOR box(w,h) that tracks relative to the mouse * until the button comes up. The starting x and y represent * the location of the upper left hand corner of the rectangle * relative to the mouse position. This relative distance should * be maintained. A constraining rectangle is also given. The * box should not be able to be dragged out of the contraining * rectangle. */ VOID gr_dragbox(w, h, sx, sy, pc, pdx, pdy) WORD w, h; REG WORD sx, sy; GRECT *pc; WORD *pdx, *pdy; { WORD offx, offy, down; GRECT o; WORD mx, my; wm_update( 3 ); gr_setup(BLACK); gr_clamp(sx+1, sy+1, 0, 0, &offx, &offy); r_set( ( WORD *)&o, sx, sy, w, h); /* get box's x,y from */ /* mouse's x,y then */ /* constrain result */ do { gsx_mxmy(&mx, &my); o.g_x = mx - offx; o.g_y = my - offy; rc_constrain(pc, &o); down = gr_wait(&o, &gl_rzero, mx, my); } while (down); *pdx = o.g_x; *pdy = o.g_y; wm_update( 2 ); } /* gr_dragbox */ /* * Draw a moving XOR box(w,h) that moves from a point whose upper * left corner is at src_x, src_y to a point at dst_x, dst_y */ VOID gr_movebox(w, h, srcx, srcy, dstx, dsty) WORD w, h; REG WORD srcx, srcy; WORD dstx, dsty; { REG WORD i; REG WORD signx, signy; WORD cnt, xstep, ystep; signx = (srcx < dstx) ? -1 : 1; signy = (srcy < dsty) ? -1 : 1; gr_scale(signx*(srcx-dstx), signy*(srcy-dsty), &cnt, &xstep, &ystep); gsx_moff(); for (i=0; i<2; i++) gr_xor(FALSE, cnt, srcx,srcy, w,h, signx*xstep, signy*ystep, FALSE); gsx_mon(); } /* gr_movebox */ /* * Draw an small box that moves from the origin x,y to a spot * centered within the rectangle and then expands to match the * size of the rectangle. */ VOID gr_growbox(po, pt) REG GRECT *po; GRECT *pt; { REG WORD i; WORD cx, cy; WORD cnt, xstep, ystep; gr_stepcalc(po->g_w, po->g_h, pt, &cx, &cy, &cnt, &xstep, &ystep); gr_movebox(po->g_w, po->g_h, po->g_x, po->g_y, cx, cy); gsx_moff(); for (i=0; i<2; i++) gr_xor(TRUE, cnt, cx, cy, po->g_w, po->g_h, xstep, ystep, TRUE); gsx_mon(); } /* gr_growbox */ /* * Draw a box that shrinks from the rectangle given down around * a small box centered within the rectangle and then moves to the * origin point. */ VOID gr_shrinkbox(po, pt) REG GRECT *po; REG GRECT *pt; { REG WORD i; WORD cx, cy; WORD cnt, xstep, ystep; gr_stepcalc(po->g_w, po->g_h, pt, &cx, &cy, &cnt, &xstep, &ystep); gsx_moff(); for (i=0; i<2; i++) gr_xor(TRUE, cnt, pt->g_x, pt->g_y, pt->g_w, pt->g_h, -xstep, -ystep, TRUE); gsx_mon(); gr_movebox(po->g_w, po->g_h, cx, cy, po->g_x, po->g_y); } /* gr_shrinkbox */ WORD gr_watchbox(tree, obj, instate, outstate) REG LONG tree; REG WORD obj; WORD instate; WORD outstate; { REG WORD out; REG WORD state; GRECT t; gsx_sclip(&gl_rscreen); ob_actxywh(tree, obj, &t); out = FALSE; do { state = (out) ? outstate : instate; ob_change(tree, obj, state, TRUE); out = !out; } while( gr_stilldn(out, t.g_x, t.g_y, t.g_w, t.g_h) ); return( out ); } /* Change code to compensate 3D objects */ WORD gr_slidebox(tree, parent, obj, isvert) REG LONG tree; WORD parent; WORD obj; WORD isvert; { REG GRECT *pt, *pc; /* new pointer for Reg Opt */ GRECT t, c; REG LONG divnd, divis; OBJECT *objc; WORD pstate,cstate; WORD ret; pt = &t; pc = &c; /* get the parent real position */ ob_actxywh(tree, parent, pc); /* get the relative position */ ob_relxywh(tree, obj, pt); objc = ( OBJECT *)tree; pstate = objc[parent].ob_flags; cstate = objc[obj].ob_flags; if ( pstate & IS3DOBJ ) pstate = 1; else pstate = 0; if ( cstate & IS3DOBJ ) cstate = 1; else cstate = 0; if ( cstate ) /* if the child is 3D, then adjust its size */ { pt->g_x -= ADJ3DPIX; pt->g_y -= ADJ3DPIX; pt->g_w += (ADJ3DPIX << 1); pt->g_h += (ADJ3DPIX << 1); } if ( pstate ) { pc->g_x -= ADJ3DPIX; pc->g_y -= ADJ3DPIX; pc->g_w += (ADJ3DPIX << 1); pc->g_h += (ADJ3DPIX << 1); } gr_dragbox( pt->g_w, pt->g_h, pt->g_x + pc->g_x, pt->g_y + pc->g_y, pc, &pt->g_x, &pt->g_y ); if ( cstate ) { pt->g_x += ADJ3DPIX/2; pt->g_y += ADJ3DPIX/2; } if ( isvert ) /* vertical movement */ { divnd = (LONG)(pt->g_y - pc->g_y); divis = (LONG)(pc->g_h - pt->g_h); } else /* horizontal movement */ { divnd = (LONG)(pt->g_x - pc->g_x); divis = (LONG)(pc->g_w - pt->g_w); } if (divis) { ret = ( WORD )(( divnd * 1000L ) / divis ); if ( ret > 1000 ) ret = 1000; return( ret ); } else return(0); } VOID gr_mkstate( pmx, pmy, pmstat, pkstat ) WORD *pmx, *pmy, *pmstat, *pkstat; { gsx_mxmy( pmx, pmy ); /* real mouse location */ *pmstat = gl_button; *pkstat = kstate; } /* Force mouse to a busy bee */ VOID gr_arrow( id ) WORD id; { gl_cmform = *((MFORM*)ad_armice); gl_mkind = M_ARROW; gl_mfid = id; gsx_mfset( ad_armice ); } /* Force mouse to a busy bee */ VOID gr_bee( id ) WORD id; { gl_cmform = *((MFORM*)ad_armice); gl_mkind = M_ARROW; gl_mfid = id; gsx_mfset( ad_hgmice ); gl_mkind = M_BEE; } /* Check for if it is OK to change the mouse */ WORD gr_mcheck( VOID ) { if ( gl_mkind & 0x8000 ) /* if mouse owns by somebody */ { if ( ( currpd->p_pid == gl_mfid ) || ( !currpd->p_pid ) ) return( TRUE ); } else { if ( ( ( gl_mkind & 0x7FFF ) == M_ARROW ) || ( currpd->p_pid == gl_mfid ) ) return( TRUE ); } return( FALSE ); } /* In all the previous version of TOS, the mouse form can be changed * by any of the applications at any time and it will be very confusing. * Now the MultiTOS will take a more radical approach. * When the mouse is in ARROW form, it is called the natural state and * only at this time that the mouse can be changed to some other form. The * mouse form ownership will belong to this application. * Any other applications which want to change the mouse form will be denied * except the M_OFF, M_ON, and M_SAVEFORM operations. * * The mouse kind is documented as follow: * If bit #15 is set, then the caller wants to do save and * set operation, and the caller will own the current mouse form * However, if the current already owns by somebody else, it will return * error. * If bit #14 is set, then it has the same effect of saving and setting the * the mouse, plus it will change the mouse ownership regardless. */ WORD gr_mouse( kind, grmaddr ) REG WORD kind; MFORM *grmaddr; { LONG *maddr; WORD mkind,ret; if ( kind & 0x4000 ) /* if bit 14 is set then make sure 15 is set too */ kind |= 0x8000; if ( kind & 0x8000 ) /* take control of the mouse */ { if ( gl_mkind & 0x8000 ) { if ( gl_mfid != currpd->p_pid ) { if ( !( kind & 0x4000 ) || !( currpd->p_type & AESSYSTEM ) )/* force mode */ return( FALSE ); } } /* save the current mouse form */ if ( kind & 0x4000 ) { currpd->p_mouse.moform = gl_cmform; currpd->p_mouse.mokind = gl_mkind; currpd->p_mouse.moid = gl_mfid; } } ret = TRUE; mkind = kind & 0x3FFF; /* mask out the bit 15 and 14 */ if ( mkind > M_USERDEFINE ) { /* system function */ switch( mkind ) { case M_OFF: /* Mouse off 256 */ currpd->p_mouse.moff++; gsx_moff(); break; case M_ON: /* Mouse on 257 */ if ( currpd->p_mouse.moff ) { currpd->p_mouse.moff--; gsx_mon(); } break; case M_SAVEFORM: /* save mouse form into */ currpd->p_mouse.moform = gl_cmform;/* the process's context */ currpd->p_mouse.mokind = gl_mkind; currpd->p_mouse.moid = gl_mfid; break; case M_RESTORE: /* restore saved mouse form */ if ( ( ret = gr_mcheck() ) ) { gl_cmform = currpd->p_mouse.moform; gl_mkind = currpd->p_mouse.mokind & ~0xC000; gl_mfid = currpd->p_mouse.moid; gsx_mfset( (LONG)&gl_cmform ); } break; case M_PREVIOUS: /* restore to previous mouse form */ if ( ( ret = gr_mcheck() ) ) { gl_cmform = gl_omform; gl_mkind = gl_omkind; gl_mfid = gl_omfid; gsx_mfset( (LONG)&gl_cmform ); } break; default: ret = FALSE; } } else { if ( !( kind & 0x8000 ) ) /* not try to take mouse ownership */ { if ( !gr_mcheck() ) /* failed the checking */ return( FALSE ); } if ( mkind != M_USERDEFINE ) /* set new mouse form */ { rs_gaddr(ad_sysglo, R_FRIMG, 0, ( LONG *)&maddr); grmaddr = ( MFORM *)LLGET( maddr[MICE0 + mkind] ); } gsx_mfset( ( LONG )grmaddr ); /* set new mouse form */ gl_mkind = kind & ~0x4000; /* do these after gsx_mfset */ gl_mfid = currpd->p_pid; } return( ret ); }