#include #include #include "ext.h" #include "ext_user.h" #include "ext_anim.h" #include "ext_common.h" #define MINHEIGHT 10 #define S_MAX 1 #define DefaultWidth 18 typedef void *(*makemethod)(void *p, long x, long y, long w, long f, long n1, long n2, long n3, long n4); fptr *FNS; typedef struct hd { GWorldPtr gw; /* could do as union */ BitMapHandle bits; short kind; /* 0 B&W, non-zero color */ short size; short refCount; short unused; struct hd *next; } KnobRec; typedef struct { Box s_box; /* heart of user interface objects */ void *s_qelem; Point s_origin; /* where mouse was clicked */ long s_val; /* current lo value */ long s_oval; /* current local value SDE */ long s_rVal; /* received (non-constrained) value */ long s_dVal; /* current hi value */ long s_size; /* size (width) in pixels */ long s_height; /* height */ long s_max; /* maximum value */ short s_last; /* place where mouse was clicked */ short s_factor; /* dividing factor for moving the slider */ short s_newwhat; short s_incolor; /* use fancy color mode */ long s_oldmax; long s_min; long s_mult; KnobRec *s_knob; short s_local; // sde set to 1 to draw when clicked, 0 to draw only on "set" short s_resolution; // sde milliseconds, resolution of output void *s_clock; // sde clock function short s_gate; // sde do we output the value? short s_unsent; // sde is there a value pending to output? long s_lval; // sde local value pending output long s_prevout; // sde previous output value; } HSlider; void *hslider_class; Rect screenRect; PaletteHandle patcherPalette; KnobRec *knobHead; void *MakeKnob(short size, short kind); short hslider_usecolor(void); void hslider_initcolor(void); void SetPColor(short index); void UnlinkKnob(KnobRec *kr); KnobRec *FindKnob(KnobRec *oldKnob, short size, short inColor); void DrawSliderPic(Rect *r); void BitCalcBaseAddr(BitMapHandle bh); void CopySliderBits(HSlider *x, short left, short top); void hslider_drag(HSlider *s, Point pt, short but); long HSliderPosToVal(HSlider *s, short coord); short HSliderValToPos(HSlider *s, long val); void MoveToCenter(Rect *b); void ChangeHSlider(HSlider *x, long newval); void OutputHSlider(HSlider *x, short lockit, long value); void OutputHSliderNormal(HSlider *x); void RedrawHSlider(HSlider *x, short src); void DrawHSlider(HSlider *x); void ColorBackgroundRect(HSlider *x, Rect *pr); void DrawColorBackground(HSlider *x); void hslider_click(HSlider *x, Point pt); void hslider_bang(HSlider *x); void hslider_assist(HSlider *x, void *b, long m, long a, char *s); void hslider_int(HSlider *x, long n); void hslider_set(HSlider *x, long n); void hslider_checksize(HSlider *x, short force); void hslider_size(HSlider *x, long n); void hslider_float(HSlider *x, double f); void hslider_update(HSlider *x); void hslider_erase(HSlider *x); void hslider_qfn(HSlider *x); void hslider_assign(HSlider *x); void hslider_psave(HSlider *x, void *w); void hslider_min(HSlider *x, long n); void hslider_mult(HSlider *x, long n); void hslider_docolor(HSlider *x); void hslider_color(HSlider *x, long r); void hslider_preset(HSlider *x); void hslider_free(HSlider *x); void *rhslider_new(void *patcher, long x, long y, long w, long s, long r, long mul, long u, long color); void *hslider_new(Symbol *s, short ac, Atom *av); void hslider_refactor(HSlider *x); void *mhslider_new(void *p, long x, long y, long font); void *lpatchbox(void *p, makemethod fn, short ac, Atom *av, short defwidth, short defcolor); short PtNearPt(Point a, Point b, short err); void MoveMouseTo(Point *pt); void StartCursorCheckTask(void); void CursorVBL(void); void StopCursorCheckTask(void); void hslider_tick(HSlider *x); // sde void hslider_resolution(HSlider *x, long n); // sde void hslider_local(HSlider *x, long state); // sde void main(void) { setup((t_messlist **)&hslider_class, (method)hslider_new, (method)hslider_free, (short)sizeof(HSlider), (method)mhslider_new, A_GIMME, 0); addint((method)hslider_int); addfloat((method)hslider_float); addbang((method)hslider_bang); addmess((method)hslider_update, "update", A_CANT, 0); addmess((method)hslider_click, "click", A_CANT, 0); addmess((method)hslider_psave, "psave", A_CANT, 0); addmess((method)hslider_set, "set", A_LONG,0); addmess((method)inspector_open, "info", A_CANT,0); addmess((method)hslider_size, "size", A_LONG,0); addmess((method)hslider_color, "color", A_LONG,0); addmess((method)hslider_preset, "preset", 0); addmess((method)hslider_assist, "assist", A_CANT,0); addmess((method)hslider_local, "local", A_LONG,0); // sde addmess((method)hslider_resolution, "resolution", A_LONG,0); // sde addmess((method)hslider_mult, "mult", A_LONG,0); addmess((method)hslider_min, "min", A_LONG,0); rescopy('STR#',3127); hslider_initcolor(); } void *MakeKnob(short size, short kind) { long bmSize; Rect r,bounds; short len,height,rowBytes; BitMapHandle bh; GrafPort g; GrafPtr savePort; Pattern p28; short depth; GWorldPtr myGWorld; CGrafPtr currPort; GDHandle currDev; CInfoRec cr; KnobRec *new; GetPort(&savePort); new = (KnobRec *)getbytes((short)sizeof(KnobRec)); if (kind) { SetRect(&r,0,0,8,size-4); len = r.right - r.left; height = r.bottom - r.top; SetRect(&bounds,0,0,len,height); GetGWorld (&currPort,&currDev); NewGWorld(&myGWorld,8,&bounds,NIL,NIL,0); SetGWorld (myGWorld,NIL); LockPixels (myGWorld->portPixMap); /* draw background */ SetPColor(21); PaintRect(&bounds); /* draw lighter shadow */ SetPColor(24); MoveTo(0,bounds.bottom-1); LineTo(bounds.right-1,bounds.bottom-1); LineTo(bounds.right-1,bounds.bottom-3); /* draw darker shadow */ SetPColor(26); MoveTo(bounds.right-1,bounds.bottom-4); LineTo(bounds.right-1,2); /* draw black */ SetPColor(1); MoveTo(0,bounds.bottom-2); LineTo(bounds.right-2,bounds.bottom-2); LineTo(bounds.right-2,0); MoveTo(bounds.right-1,1); Line(0,0); /* draw white */ SetPColor(0); MoveTo(bounds.right-3,0); LineTo(0,0); LineTo(0,bounds.bottom-3); UnlockPixels (myGWorld->portPixMap); SetGWorld (currPort,currDev); new->gw = myGWorld; new->kind = 1; new->size = size; new->refCount = 0; } else { SetRect(&r,0,0,10,size-4); len = r.right - r.left; height = r.bottom - r.top; rowBytes = ((len/16) +1) * 2; bmSize = sizeof(BitMap) + (rowBytes * (height + 1)); bh = (BitMapHandle)NewHandle(bmSize); HLock((Handle)bh); (*bh)->rowBytes = rowBytes; BitCalcBaseAddr(bh); SetRect(&bounds,0,0,len,height); (*bh)->bounds = bounds; OpenPort(&g); g.portRect = bounds; SetPortBits(*bh); /* if (x->s_max == 1) { GetIndPattern(p28,sysPatListID,4); PenPat(p28); } */ DrawSliderPic(&bounds); HUnlock((Handle)bh); ClosePort(&g); SetPort(savePort); new->bits = bh; new->kind = 0; new->size = size; new->refCount = 0; } new->next = knobHead; knobHead = new; return (new); } short hslider_usecolor(void) { CInfoRec cr; short kind; /* eventually get the max variable which dynamically changes */ colorinfo(&cr); return (cr.c_has32bitQD && cr.c_depth >= 4 ? 1 : 0); } void hslider_initcolor(void) { CInfoRec cr; short kind; KnobRec *kr; short depth; knobHead = 0; colorinfo(&cr); kind = cr.c_has32bitQD && cr.c_depth >= 4 ? 1 : 0; if (kind) patcherPalette = GetNewPalette(9997); else patcherPalette = 0; MakeKnob(DefaultWidth,kind); } void SetPColor(short index) { RGBColor rgb; if (!patcherPalette) return; GetEntryColor(patcherPalette,index,&rgb); RGBForeColor(&rgb); } void UnlinkKnob(KnobRec *kr) { KnobRec *t,*prev; if (!kr) return; if (kr->size == DefaultWidth) /* don't delete the default */ return; if (--kr->refCount <= 0) { for (t = knobHead, prev = 0; t; prev = t, t = t->next) { if (t == kr) { if (prev) prev->next = t->next; else knobHead = t->next; if (kr->kind) DisposeGWorld(kr->gw); else DisposeHandle((Handle)kr->bits); freebytes(kr,(short)sizeof(KnobRec)); break; } } } } KnobRec *FindKnob(KnobRec *oldKnob, short size, short inColor) { register KnobRec *kr; short foundit; foundit = FALSE; for (kr = knobHead; kr; kr = kr->next) { if ((kr->size == size) && (kr->kind == inColor)) { foundit = TRUE; break; } } if (!foundit) kr = MakeKnob(size,inColor); if (kr != oldKnob) { UnlinkKnob(oldKnob); kr->refCount++; } return (kr); } void DrawSliderPic(Rect *r) { Rect f; f = *r; EraseRect(&f); f.bottom--; f.right--; FrameRect(&f); MoveTo(f.right,1); LineTo(f.right,f.bottom); LineTo(1,f.bottom); MoveTo(2,2); LineTo(2,f.bottom-3); MoveTo(4,2); LineTo(4,f.bottom-3); MoveTo(6,2); LineTo(6,f.bottom-3); } void BitCalcBaseAddr(BitMapHandle bh) { Byte *b; b = (Byte *)*bh; (*bh)->baseAddr = (char *)((QDPtr)b + sizeof(BitMap)); } void CopySliderBits(HSlider *x, short left, short top) { Rect dst; GrafPtr p; BitMapHandle bits; PixMapHandle ph; GetPort(&p); if (x->s_incolor) { ph = x->s_knob->gw->portPixMap; dst = (*ph)->bounds; OffsetRect(&dst,left,top); CopyBits((BitMap *)*ph,&p->portBits,&(*ph)->bounds,&dst,srcCopy,0L); } else { bits = x->s_knob->bits; dst = (*bits)->bounds; OffsetRect(&dst,left,top); HLock((Handle)bits); BitCalcBaseAddr(bits); CopyBits((*bits),&p->portBits,&(*bits)->bounds,&dst,srcCopy,0L); HUnlock((Handle)bits); } } void hslider_drag(HSlider *s, Point pt, short but) { char savelock; long val,diff; short coord; Point gp,p; if (but) { if (s->s_local) // sde val = s->s_val; else val = s->s_oval; diff = (pt.h - s->s_last)/s->s_factor; if (diff) { val += diff; if (val < 0) val = 0; if (val >= s->s_max) val = s->s_max-1; ChangeHSlider(s,val); s->s_last = pt.h; } gp = pt; LocalToGlobal(&gp); if (!PtInRect(gp,&screenRect)) { MoveToCenter(&screenRect); GetMouse(&gp); s->s_last = gp.h; } } else { coord = HSliderValToPos(s,s->s_val); p.h = coord+(s->s_incolor?1:2); /* fudge factor so mouse doesn't move */ p.v = s->s_box.b_rect.top + ((s->s_box.b_rect.bottom - s->s_box.b_rect.top)>>1); LocalToGlobal(&p); MoveMouseTo(&p); StopCursorCheckTask(); ShowCursor(); } } long HSliderPosToVal(HSlider *s, short coord) { short firstThing,pix; long res; firstThing = s->s_box.b_rect.left + 8; /* some box boundary constant (bar->min) */ //if (s->s_incolor) // firstThing--; pix = coord - firstThing; if (pix < 0) pix = 0; res = (pix * (s->s_max - 1))/s->s_size; if (res < 0) res = 0; if (res >= s->s_max) res = s->s_max - 1; return (res); /* typically size/range */ } short HSliderValToPos(HSlider *s, long val) { short firstThing; long m; m = s->s_max < 2 ? 1 : s->s_max - 1; firstThing = s->s_box.b_rect.left + 8; return ((short)((val * s->s_size)/m) + firstThing); } void ChangeHSlider(HSlider *x, long newval) { if (x->s_local) x->s_rVal = newval; if (newval == x->s_val) return; if (x->s_local) x->s_val = newval; else x->s_oval = newval; OutputHSlider(x,TRUE,newval); if (x->s_local) qelem_set(x->s_qelem); } void OutputHSlider(HSlider *x, short lockit, long value) { long out; short savelock; if (x->s_gate) { // sde x->s_unsent = 0; if (lockit) savelock = lockout_set(1); out = x->s_min + (value * x->s_mult); // sde outlet_int(x->s_box.b_ob.o_outlet,out); x->s_prevout = out; if (lockit) lockout_set(savelock); if (x->s_resolution) { x->s_lval = value; x->s_gate = 0; // sde don't allow values to be sent until clock goes off. clock_delay(x->s_clock,(long)x->s_resolution); } } else { x->s_lval=value; x->s_unsent=1; } } void OutputHSliderNormal(HSlider *x) { outlet_int(x->s_box.b_ob.o_outlet,x->s_min + (x->s_val * x->s_mult)); } void RedrawHSlider(HSlider *x, short src) { Rect r; short c1,c2; long d,v; v = x->s_val; if (!src && (x->s_dVal==v)) return; c1 = HSliderValToPos(x,x->s_dVal); c2 = HSliderValToPos(x,v); r = x->s_box.b_rect; if (x->s_incolor) { InsetRect(&r,0,2); r.bottom++; r.top++; if (c1 == c2) { x->s_dVal = v; return; } if (c1 < c2) { r.left = c1-4; r.right = c2-4; } else { r.left = c2 + 4; r.right = c1+4; } CopySliderBits(x,c2-4,r.top); ColorBackgroundRect(x,&r); } else { InsetRect(&r,0,2); if (c1 < c2) { r.left = c1-5; r.right = c2-5; } else { r.left = c2 + 5; r.right = c1+5; } CopySliderBits(x,c2-5,r.top); EraseRect(&r); } x->s_dVal = v; } void DrawHSlider(HSlider *x) { Rect r; short coord; if (x->s_incolor) { DrawColorBackground(x); } coord = HSliderValToPos(x,x->s_dVal); r = x->s_box.b_rect; if (x->s_incolor) CopySliderBits(x,coord-4,r.top+3); else CopySliderBits(x,coord-5,r.top+2); } void ColorBackgroundRect(HSlider *x, Rect *pr) { RGBColor saveF; Rect middle,r; GetForeColor(&saveF); forecolor(21,true); r = *pr; MoveTo(r.left,r.top); LineTo(r.right-1,r.top); PenSize(1,2); MoveTo(r.left,r.bottom-2); LineTo(r.right-1,r.bottom-2); PenNormal(); forecolor(26,true); MoveTo(r.left,r.top+1); LineTo(r.right-1,r.top+1); box_color((void *)x); middle = r; middle.top += 2; middle.bottom -= 3; PaintRect(&middle); forecolor(0,true); MoveTo(r.left,r.bottom-3); LineTo(r.right-1,r.bottom-3); RGBForeColor(&saveF); } void DrawColorBackground(HSlider *x) { Rect r,r1; RGBColor saveF; r = r1 = x->s_box.b_rect; InsetRect(&r,1,1); GetForeColor(&saveF); forecolor(21,true); PaintRect(&r); box_color((void *)x); InsetRect(&r1,4,4); r1.top++; PaintRect(&r1); PenNormal(); forecolor(0,true); MoveTo(r1.left,r1.bottom); LineTo(r1.right-1,r1.bottom); MoveTo(r1.right,r1.bottom-1); LineTo(r1.right,r1.top); forecolor(26,true); MoveTo(r1.left,r1.top-1); LineTo(r1.right-1,r1.top-1); forecolor(27,true); MoveTo(r1.left-1,r1.top-1); LineTo(r1.left-1,r1.bottom-1); RGBForeColor(&saveF); } void hslider_click(HSlider *x, Point pt) { long score; if (x->s_max<=1) return; x->s_prevout = -999999; // sde kludge x->s_last = pt.h; score = HSliderPosToVal(x,pt.h); if (x->s_local) // sde DONT UPDATE IT x->s_rVal = x->s_val = score; else x->s_oval = score; OutputHSlider(x,TRUE,score); if (x->s_local) RedrawHSlider(x,FALSE); StartCursorCheckTask(); HideCursor(); screenRect = (*LMGetGrayRgn())->rgnBBox; InsetRect(&screenRect,4,4); wind_drag((void *)hslider_drag, x, pt); } void hslider_bang(HSlider *x) { OutputHSliderNormal(x); } void hslider_assist(HSlider *x, void *b, long m, long a, char *s) { assist_string(3127,m,a,1,2,s); } void hslider_int(HSlider *x, long n) { x->s_rVal = n; if (n >= x->s_max) n = x->s_max - 1; if (n < 0) n = 0; x->s_val = n; OutputHSlider(x,FALSE,x->s_val); qelem_set(x->s_qelem); } void hslider_set(HSlider *x, long n) { x->s_rVal = n; if (n >= x->s_max) n = x->s_max - 1; if (n < 0) n = 0; x->s_val = n; qelem_set(x->s_qelem); } void hslider_checksize(HSlider *x, short force) { Rect *r; long n,w; short s; r = &x->s_box.b_rect; n = r->bottom - r->top; w = r->right - r->left; if (w != x->s_size + 16) { x->s_size = w - 16; if (x->s_size < 1) { x->s_size = 1; box_size(x,17,r->bottom - r->top); } hslider_refactor(x); } if (n != x->s_height || force) { if (n < MINHEIGHT) { x->s_height = MINHEIGHT; n = MINHEIGHT; s = x->s_size+15; box_size(x,s,MINHEIGHT); } x->s_height = n; x->s_knob = FindKnob(x->s_knob,n,x->s_incolor); } } void hslider_size(HSlider *x, long n) /* change the max of the slider, resize the box */ { if (n < 1) n = 2; x->s_oldmax = x->s_max; x->s_newwhat = S_MAX; x->s_max = n; qelem_set(x->s_qelem); } void hslider_docolor(HSlider *x) { GrafPtr gp; if (gp = patcher_setport(x->s_box.b_patcher)) { if (!box_nodraw((t_box *)x)) { DrawHSlider(x); box_enddraw((t_box *)x); } SetPort(gp); } } void hslider_color(HSlider *x, long r) { if (r >= 0 && r < 34) { x->s_box.b_color = r; defer(x,(void *)hslider_docolor,0L,0,0L); } } void hslider_preset(HSlider *x) { preset_int(x,x->s_val); } void hslider_refactor(HSlider *x) { x->s_factor = (short)(x->s_size / x->s_max); if (x->s_factor < 1) x->s_factor = 1; } void hslider_float(HSlider *x, double f) { hslider_int(x, (long)f); } void hslider_update(HSlider *x) { short oldcolor; oldcolor = x->s_incolor; x->s_incolor = hslider_usecolor(); hslider_checksize(x, oldcolor != x->s_incolor); DrawHSlider(x); } void hslider_erase(HSlider *x) { Rect r; r = x->s_box.b_rect; InsetRect(&r,2,2); EraseRect(&r); } void hslider_qfn(HSlider *x) { GrafPort *gp; gp = patcher_setport(x->s_box.b_patcher); if (gp) { if (!box_nodraw((t_box *)x)) { if (x->s_newwhat) { hslider_erase(x); hslider_assign(x); DrawHSlider(x); } else RedrawHSlider(x,TRUE); box_enddraw((t_box *)x); } else { if (x->s_newwhat) hslider_assign(x); else x->s_dVal = x->s_val; } SetPort(gp); } else { x->s_dVal = x->s_val; } } void hslider_assign(HSlider *x) { Boolean redoBits = FALSE; switch (x->s_newwhat) { case S_MAX: if (x->s_oldmax==1 || x->s_max==1) redoBits = TRUE; x->s_val = x->s_rVal; if (x->s_val >= x->s_max) x->s_val = x->s_max - 1; if (x->s_val < 0) x->s_val = 0; x->s_dVal = x->s_val; if (redoBits) { x->s_knob = FindKnob(x->s_knob,x->s_height,x->s_incolor); } hslider_refactor(x); break; default: break; } x->s_newwhat = 0; } void hslider_psave(HSlider *x, void *w) { Rect *r; r = &x->s_box.b_rect; if (x->s_box.b_hidden) { binbuf_vinsert(w,"ssssllllllll", gensym("#P"),gensym("hidden"),gensym("user"), gensym("hslider"), (long)(r->left), (long)(r->top), (long)(r->bottom - r->top), (long)(x->s_size),(long)(x->s_max), x->s_mult,x->s_min,(long)x->s_box.b_color); } else { binbuf_vinsert(w,"sssllllllll", gensym("#P"),gensym("user"), gensym("hslider"), (long)(r->left), (long)(r->top), (long)(r->bottom - r->top), (long)(x->s_size),(long)(x->s_max), x->s_mult,x->s_min,(long)x->s_box.b_color); } } void hslider_min(HSlider *x, long n) { x->s_min = n; } void hslider_mult(HSlider *x, long n) { if (n < -1024) n = -1024; else if (n > 1024) n = 1024; x->s_mult = n; } void hslider_free(HSlider *x) { notify_free((t_object *)x); UnlinkKnob(x->s_knob); qelem_free(x->s_qelem); freeobject(x->s_clock); // sde box_free((Box *)x); } void *rhslider_new(void *patcher, long x, long y, long w, long s, long r, long mul, long u, long color) { HSlider *p; p = (HSlider *)newobject(hslider_class); if (s < 1) s = 1; intout(p); box_new((Box *)p, patcher, F_DRAWFIRSTIN | F_GROWBOTH | F_SAVVY, (short)x, (short)y, (short)(x+s+16), (short)(y+w)); p->s_box.b_firstin = (void *)p; /* it's not really an inlet */ p->s_val = p->s_rVal = 0; p->s_mult = mul==0?1:mul; p->s_newwhat = 0; p->s_min = u; p->s_dVal = 0; p->s_max = r==0?128:r; p->s_size = s; p->s_incolor = hslider_usecolor(); p->s_oldmax = p->s_max; p->s_qelem = qelem_new(p, (void *)hslider_qfn); p->s_box.b_color = color; p->s_height = p->s_box.b_rect.bottom - p->s_box.b_rect.top; p->s_knob = FindKnob(0L,p->s_height,p->s_incolor); p->s_local = 1; // sde draw it by default p->s_resolution = 0; // sde full resolution p->s_clock = clock_new(p,(method)hslider_tick); // sde clock for filtering p->s_unsent = 0; // sde no values pending to be sent p->s_gate = 1; // allow values to pass p->s_prevout = -9999999; hslider_refactor(p); box_ready((void *)p); return (p); } /* creating sliders with default values */ void *hslider_new(Symbol *s, short ac, Atom *av) { void *p; void *res; p = (void *)av[0].a_w.w_obj; av++; ac--; res = lpatchbox(p, (makemethod)rhslider_new, ac, av, 128, 0); return (res); } void hslider_tick(HSlider *x) // sde { long out; if (x->s_unsent) { if (x->s_local) out = x->s_min + (x->s_val * x->s_mult); else out = x->s_min + (x->s_lval * x->s_mult); x->s_gate = 0; // don't allow data to pass if (out != x->s_prevout) { x->s_prevout = out; if (x->s_local) outlet_int(x->s_box.b_ob.o_outlet,x->s_min + (x->s_val * x->s_mult)); else outlet_int(x->s_box.b_ob.o_outlet,x->s_min + (x->s_lval * x->s_mult)); } x->s_unsent = 0; if (x->s_resolution) clock_delay(x->s_clock,(long)x->s_resolution); else x->s_gate = 1; // allow data to pass } else x->s_gate = 1; // allow next value to pass, and don't reset clock } void hslider_resolution(HSlider *x, long n) // sde { if (n >= 5) x->s_resolution = (short)n; else x->s_resolution = 0; /* don't limit at all */ if (!x->s_resolution) { clock_unset(x->s_clock); x->s_gate = 1; } } void hslider_local(HSlider *x, long state) // sde { x->s_local = state; } void *mhslider_new(void *p, long x, long y, long font) { void *res; res = rhslider_new(p,x,y,18L, 128L, 128L, 0L, 0L, 0L); return (res); } /* utilities */ void *lpatchbox(void *p,makemethod fn, short ac, Atom *av, short defwidth, short defcolor) { long x, y, w, f, n1, n2, n3, n4; if (ac < 2 || av[0].a_type != A_LONG || av[1].a_type != A_LONG) x = y = 50; else x = av[0].a_w.w_long, y = av[1].a_w.w_long; if (ac < 3 || av[2].a_type != A_LONG) w = defwidth; else w = av[2].a_w.w_long; if (ac < 4 || av[3].a_type != A_LONG) f = 0; else f = av[3].a_w.w_long; if (ac < 5 || av[4].a_type != A_LONG) n1 = 0; else n1 = av[4].a_w.w_long; if (ac < 6 || av[5].a_type != A_LONG) n2 = 0; else n2 = av[5].a_w.w_long; if (ac < 7 || av[6].a_type != A_LONG) n3 = 0; else n3 = av[6].a_w.w_long; if (ac < 8 || av[7].a_type != A_LONG) n4 = defcolor; else n4 = av[7].a_w.w_long; return ((*fn)(p, x, y, w, f, n1, n2, n3, n4)); } short PtNearPt(Point a, Point b, short err) { Rect r; r.left = b.h - err; r.right = b.h + err; r.top = b.v - err; r.bottom = b.v + err; return (PtInRect(a,&r)); } #define Consec_Thresh 5 typedef struct VBLRec { VBLTask myVBLTask; long vblA5; /* 4 bytes before the VBLTask data */ } VBLRec, *VBLRecPtr; VBLRec gMyVBLRec; VBLUPP cursorCheckUPP = 0; short gTaskInterval; WindowPtr gTheWindow; short gConsecCount; #ifndef powerc pascal long GetVBLRec (void); pascal long GetVBLRec (void) = 0x2E88; #endif void StartCursorCheckTask(void) { if (!cursorCheckUPP) cursorCheckUPP = NewVBLProc(CursorVBL); gTheWindow = FrontWindow(); gMyVBLRec.myVBLTask.qType = vType; gMyVBLRec.myVBLTask.vblAddr = cursorCheckUPP; gMyVBLRec.myVBLTask.vblCount = gTaskInterval = 6; /* Set the interval */ #ifndef powerc gMyVBLRec.vblA5 = (long) LMGetCurrentA5(); /* Save app's A5 in structure */ #endif VInstall((QElemPtr) &gMyVBLRec.myVBLTask); gConsecCount = 0; } /* ============= the VBL task code itself =============*/ void CursorVBL(void) { short interval; #ifndef powerc long curA5; VBLRecPtr recPtr; long oldA4; recPtr = (VBLRecPtr)GetVBLRec(); curA5 = SetA5 (recPtr->vblA5); oldA4 = SetUpA4(); #endif if (gTheWindow != FrontWindow()) { if (++gConsecCount > Consec_Thresh) { ShowCursor(); interval = 0; // your work is done } else interval = gTaskInterval; } else { gConsecCount = 0; interval = gTaskInterval; } #ifndef powerc recPtr->myVBLTask.vblCount = interval; RestoreA4(oldA4); curA5 = SetA5(curA5); #else gMyVBLRec.myVBLTask.vblCount = interval; #endif } void StopCursorCheckTask(void) { if (gTaskInterval) VRemove((QElemPtr) &gMyVBLRec.myVBLTask); gTaskInterval = 0; // easier than VRemove because we don't know if it's still there }