#include <stdio.h> #include <exec/types.h> #include <intuition/intuitionbase.h> #include <intuition/intuition.h> #include <intuition/screens.h> #include <graphics/clip.h> #include <devices/inputevent.h> #include <clib/exec_protos.h> #include <clib/intuition_protos.h> #include <clib/layers_protos.h> #include "WheelMouse.h" #include "Scroll.h" #include "RawKey.h" extern struct IntuitionBase *IntuitionBase; struct Window *WindowUnderPointer(); /* With any luck this will fix reported CyberGuard hits with MUI programs. */ struct { char a,b,c,d; } DeadKeyData; void SendIDCMP(struct WheelMouseContext *wmc,int class,int code,int qualifier,struct IntuiMessage *im) { struct Window *win=wmc->Window; struct Gadget *gg=wmc->Gadget; im->IDCMPWindow=win; if(class==IDCMP_RAWKEY) im->IAddress=&DeadKeyData; else im->IAddress=gg; im->Class=class; im->Code=code; im->Qualifier=qualifier; im->MouseX=win->MouseX; im->MouseY=win->MouseY; im->ExecMessage.mn_ReplyPort=wmc->ReplyPort; im->Seconds=IntuitionBase->Seconds; im->Micros=IntuitionBase->Micros; im->SpecialLink=NULL; PutMsg(win->UserPort,(struct Message *)im); } void NudgePropGadget(struct Gadget *gg,struct Window *win,int axis,int direction) { struct PropInfo *pi=(struct PropInfo *)gg->SpecialInfo; long current,offset; if(axis&FREEVERT) { current=pi->VertPot; offset=pi->VPotRes; current+=(direction*offset)/3; if(current<0) current=0; if(current>0xffff) current=0xffff; pi->VertPot=current; } if(axis&FREEHORIZ) { current=pi->HorizPot; offset=pi->HPotRes; current+=(5*(direction*offset))/8; if(current<0) current=0; if(current>0xffff) current=0xffff; pi->HorizPot=current; } } struct Gadget *FindPropGadget(struct Window *win,long type) { struct Gadget *gg=win->FirstGadget,*bestgadget=NULL; int gx,gy,gt,gl,gw,gh,dd,distance=32767; while(gg) { if((gg->GadgetType>YP_GTYPEMASK)==GTYP_PROPGADGET) { struct PropInfo *pi=(struct PropInfo *)gg->SpecialInfo; if(pi) { if(pi->Flags&type) { dd=32767; gl=gg->LeftEdge; gt=gg->TopEdge; gw=gg->Width; gh=gg->Height; if(gg->Flags&GFLG_RELRIGHT) gl+=win->Width; if(gg->Flags&GFLG_RELBOTTOM) gt+=win->Height; if(gg->Flags&GFLG_RELWIDTH) gw+=win->Width; if(gg->Flags&GFLG_RELHEIGHT) gh+=win->Height; if(pi->Flags&FREEVERT) { gx=gl+gw; dd=gx-win->MouseX; if(dd<0) dd=-dd+win->Width; /* bias to left of scrollbar */ gy=(gt+gh)-win->MouseY; if((gt-win->MouseY)*(gt-win->MouseY)<(gy*gy)) gy=gt-win->MouseY; if(gy<0) gy=-gy; dd+=gy; } if(pi->Flags&FREEHORIZ) { gx=win->MouseX-gl; gy=win->MouseY-gt; if((gx>=-2)&&(gy>=-2)&&(gx<=(gw+2))&&(gy<=(gh+2))) dd=1; } if(dd<0) dd=-dd; if(dd<distance) { distance=dd; bestgadget=gg; } } } } gg=gg->NextGadget; } return(bestgadget); } int DoScroll(struct WheelMouseContext *wmc,int axis,int direction) { struct Window *win; Forbid(); if(wmc->WindowMode==OverWindow) win=wmc->Window=WindowUnderPointer(); else win=wmc->Window=IntuitionBase->ActiveWindow; if(!(win)) return(direction); wmc->Gadget=FindPropGadget(win,axis); if((!(wmc->Gadget))&&(wmc->WindowMode==OverWindow)&&((win->IDCMPFlags&IDCMP_RAWKEY)==0)) { if(!(win=wmc->Window=IntuitionBase->ActiveWindow)) return(direction); wmc->Gadget=FindPropGadget(win,axis); } if(wmc->Gadget) { NudgePropGadget(wmc->Gadget,win,axis,direction); SendIDCMP(wmc,IDCMP_GADGETDOWN,0,0,&wmc->Msg1.eim_IntuiMessage); SendIDCMP(wmc,IDCMP_GADGETUP,0,0,&wmc->Msg2.eim_IntuiMessage); RefreshGList(wmc->Gadget,wmc->Window,NULL,1); Permit(); WaitPort(wmc->ReplyPort); GetMsg(wmc->ReplyPort); WaitPort(wmc->ReplyPort); GetMsg(wmc->ReplyPort); return(direction); } else if(win->IDCMPFlags&IDCMP_RAWKEY) { int code,c,d,q=0; d=direction; if(d>0) if(axis&FREEVERT) code=RK_Down; else code=RK_Right; else { if(axis&FREEVERT) code=RK_Up; else code=RK_Left; d=-d; } if(d>1) q=IEQUALIFIER_LSHIFT; SendIDCMP(wmc,IDCMP_RAWKEY,code,q,&wmc->Msg1.eim_IntuiMessage); SendIDCMP(wmc,IDCMP_RAWKEY,code|IECODE_UP_PREFIX,q,&wmc->Msg2.eim_IntuiMessage); Permit(); WaitPort(wmc->ReplyPort); GetMsg(wmc->ReplyPort); WaitPort(wmc->ReplyPort); GetMsg(wmc->ReplyPort); return(direction); } Permit(); return(direction); } struct Window *WindowUnderPointer() { int x,y; unsigned long lock; struct Window *win=NULL; struct Screen *scr; struct Layer *layer; scr=IntuitionBase->FirstScreen; do { x=scr->MouseX; y=scr->MouseY; if((x<0) || (y<0)) scr=scr->NextScreen; } while((scr!=NULL) && ((x<0)||(y<0))); if(!scr) return(NULL); layer=WhichLayer(&scr->LayerInfo,x,y); if(layer) win=layer->Window; return(win); }