home *** CD-ROM | disk | FTP | other *** search
- /* $VER: RealDrag.c 1.0 (23.4.96)
- RealDrag by Stuart Monteith
-
- Allows windows to be dragged, while their contents are still shown.
-
- Note: This source is Public Domain. Hell, this program should have been
- written years ago.
- */
-
- #include <dos/dos.h>
- #include <devices/inputevent.h>
- #include <exec/types.h>
- #include <exec/libraries.h>
- #include <intuition/intuitionbase.h>
- #include <libraries/commodities.h>
- #include <workbench/startup.h>
- #include <workbench/workbench.h>
-
- #include <clib/exec_protos.h>
- #include <clib/commodities_protos.h>
- #include <clib/icon_protos.h>
-
- struct NewBroker newBroker= {
- NB_VERSION,
- "RealDrag",
- "RealDrag 1.0 Apr-96 Stuart Monteith",
- "Alternative filled window dragging",
- NBU_NOTIFY | NBU_UNIQUE, /* Tell me when another me is started */
- 0, /* No flags. ie. no Show & Hide */
- 4, /* Priority. To be set */
- NULL, /* Message port. To Be Set */
- 0 /* Unused */
- };
-
- void Cleanup(char *errStr,ULONG errNum); /* Call to exit */
- void RealMain(void);
-
- /* This is a custom CxObject, to be executed on input.device's task.
- * __geta4 as we are compiled as a small-code model. */
- __geta4 void CxStripQualifier(CxMsg *cxm,CxObj *co);
-
- struct IntuitionBase *IntuitionBase=NULL;
- struct Library *CxBase=NULL,*IconBase=NULL;
- extern struct Library *DOSBase;
-
-
- struct MsgPort *msgPort=NULL;
-
- CxObj *broker=NULL,*filter=NULL,*sender=NULL,*stripqual=NULL;
-
- #define CXID_SENDER1 0xCED1
-
- /* Used by filter to direct mouse movements to us */
- IX ix = {
- IX_VERSION, /* IXVersion */
- IECLASS_RAWMOUSE, /* Class */
- 0, /* Code */
- 0, /* CodeMask*/
- 0, /* Qualifier */
- 0, /* Qualifier mask */
- 0};
-
- char *vers="$VER: RealDrag.c 1.0 (23.4.96)";
-
- /* ReadArgs */
- #define NUM_ARGS 12 /* # of args */
-
- /* The ReadArgs array indices */
- #define ARG_CX_PRIORITY 0
- #define ARG_TASKPRI 1
- #define ARG_CTRL 2
- #define ARG_LSHIFT 3
- #define ARG_RSHIFT 4
- #define ARG_LALT 5
- #define ARG_RALT 6
- #define ARG_LAMIGA 7
- #define ARG_RAMIGA 8
- #define ARG_LBUTTON 9
- #define ARG_RBUTTON 10
- #define ARG_MBUTTON 11
-
- /* The ReadArgs template */
- char *template="CX_PRIORITY/N/K,TASKPRI/N/K,CTRL/S"
- ",LSHIFT/S,RSHIFT/S,LALT/S,RALT/S,LAMIGA/S,RAMIGA/S,"
- "LBUTTON/S,RBUTTON/S,MBUTTON/S";
- LONG Args[NUM_ARGS];
- struct RDArgs *rdArgs = NULL;
-
- BOOL FromWB; /* True if launched from WB, false if from DOS */
-
- /* An EasyRequester displaying an error from WB */
- struct EasyStruct ez ={
- sizeof(struct EasyStruct), /* Struct Size */
- 0, /* Flags */
- "RealDrag", /* Title */
- "Error:\n%s", /* Text Format */
- "Understood" /* Gadget Format */
- };
-
-
- /* Workbench startup stuff */
- int wbmain(struct WBStartup *ws)
- {
- struct WBArg *wbArg;
- struct DiskObject *icon;
- BPTR oldlock;
- char *tt; /* ToolType */
-
- FromWB=TRUE;
-
- if(!(IconBase = OpenLibrary("icon.library",36)))
- Cleanup("Unable to open icon.library V36",
- ERROR_INVALID_RESIDENT_LIBRARY);
-
- /* If just Tool icon, use that, else use first project icon */
- if(ws->sm_NumArgs == 1)
- wbArg = &(ws->sm_ArgList[0]);
- else
- wbArg = &(ws->sm_ArgList[1]);
-
- oldlock = CurrentDir(wbArg->wa_Lock);
-
- if(!(icon = (struct DiskObject *) GetDiskObject(wbArg->wa_Name)))
- {
- CurrentDir(oldlock); /* Important!*/
- Cleanup("Unable to get icon",IoErr());
- }
- CurrentDir(oldlock);
-
- if(tt = FindToolType(icon->do_ToolTypes,"CX_PRIORITY"))
- newBroker.nb_Pri = (BYTE) atoi(tt);
-
- /* All of these args may follow `QUALIFIER=', separated by | */
- if(tt = FindToolType(icon->do_ToolTypes,"QUALIFIER"))
- {
- if(MatchToolValue(tt,"CTRL"))
- ix.ix_Qualifier |= IEQUALIFIER_CONTROL;
-
- if(MatchToolValue(tt,"LSHIFT"))
- ix.ix_Qualifier |= IEQUALIFIER_LSHIFT;
-
- if(MatchToolValue(tt,"RSHIFT"))
- ix.ix_Qualifier |= IEQUALIFIER_RSHIFT;
-
- if(MatchToolValue(tt,"LALT"))
- ix.ix_Qualifier |= IEQUALIFIER_LALT;
-
- if(MatchToolValue(tt,"RALT"))
- ix.ix_Qualifier |= IEQUALIFIER_RALT;
-
- if(MatchToolValue(tt,"LAMIGA"))
- ix.ix_Qualifier |= IEQUALIFIER_LCOMMAND;
-
- if(MatchToolValue(tt,"RAMIGA"))
- ix.ix_Qualifier |= IEQUALIFIER_RCOMMAND;
-
- if(MatchToolValue(tt,"LBUTTON"))
- ix.ix_Qualifier |= IEQUALIFIER_LEFTBUTTON;
-
- if(MatchToolValue(tt,"RBUTTON"))
- ix.ix_Qualifier |= IEQUALIFIER_RBUTTON;
-
- if(MatchToolValue(tt,"MBUTTON"))
- ix.ix_Qualifier |= IEQUALIFIER_MIDBUTTON;
- }
-
- FreeDiskObject(icon);
-
- RealMain();
- }
-
- int main(int argc,char *argv[])
- {
- int cnt;
-
- FromWB = FALSE;
-
- if(DOSBase->lib_Version <36)
- {
- printf("RealDrag: Wrong DOS version - upgrade to 2.0 or above!\n");
- exit(ERROR_INVALID_RESIDENT_LIBRARY);
- }
-
- /* NULL all args */
- for(cnt=0;cnt < NUM_ARGS;cnt++) Args[cnt] = 0l;
-
- if(!(rdArgs = (struct RDArgs *) ReadArgs(template,Args,NULL)))
- {
- PrintFault(ERROR_REQUIRED_ARG_MISSING,"RealDrag: ");
- exit(ERROR_REQUIRED_ARG_MISSING);
- }
-
- if(Args[ARG_CX_PRIORITY])
- newBroker.nb_Pri = (BYTE) *((LONG *) Args[ARG_CX_PRIORITY]);
-
- if(Args[ARG_TASKPRI])
- SetTaskPri(FindTask(NULL),*((LONG *) Args[ARG_TASKPRI]));
-
- if(Args[ARG_CTRL])
- ix.ix_Qualifier |= IEQUALIFIER_CONTROL;
-
- if(Args[ARG_LSHIFT])
- ix.ix_Qualifier |= IEQUALIFIER_LSHIFT;
-
- if(Args[ARG_RSHIFT])
- ix.ix_Qualifier |= IEQUALIFIER_RSHIFT;
-
- if(Args[ARG_LALT])
- ix.ix_Qualifier |= IEQUALIFIER_LALT;
-
- if(Args[ARG_RALT])
- ix.ix_Qualifier |= IEQUALIFIER_RALT;
-
- if(Args[ARG_LAMIGA])
- ix.ix_Qualifier |= IEQUALIFIER_LCOMMAND;
-
- if(Args[ARG_RAMIGA])
- ix.ix_Qualifier |= IEQUALIFIER_RCOMMAND;
-
- if(Args[ARG_LBUTTON])
- ix.ix_Qualifier |= IEQUALIFIER_LEFTBUTTON;
-
- if(Args[ARG_RBUTTON])
- ix.ix_Qualifier |= IEQUALIFIER_RBUTTON;
-
- if(Args[ARG_MBUTTON])
- ix.ix_Qualifier |= IEQUALIFIER_MIDBUTTON;
-
- RealMain();
- }
-
- void RealMain(void)
- {
- LONG brokerErr;
-
- if(!(IntuitionBase = (struct IntuitionBase *)OpenLibrary("intuition.library",36L)))
- Cleanup("Unable to open intuition.library",36);
-
- if(!(CxBase = OpenLibrary("commodities.library",36)))
- Cleanup("Unable to open commodities.library",
- ERROR_INVALID_RESIDENT_LIBRARY);
-
- if(!(msgPort = CreateMsgPort()))
- Cleanup("Unable to create msgport",
- RETURN_FAIL);
-
- /* We care about our qualifiers */
- ix.ix_QualMask = ix.ix_Qualifier;
-
- newBroker.nb_Port = msgPort;
-
- if(!(broker = CxBroker(&newBroker,&brokerErr)))
- {
- switch(brokerErr)
- {
- case CBERR_SYSERR:
- Cleanup("Can't create broker - syserr",RETURN_FAIL);
- case CBERR_DUP:
- Cleanup(NULL,0);
- case CBERR_VERSION:
- Cleanup("Wrong NewBroker struct version.",RETURN_FAIL);
- default:
- Cleanup("Can't create broker - don't know why",RETURN_FAIL);
- }
- }
-
- /* Checks for qualifier AFTER trying to create broker. This allows realdrag
- * to kill itself without any arguments being present. */
- if(! ix.ix_Qualifier)
- Cleanup("You MUST choose a qualifier!",ERROR_REQUIRED_ARG_MISSING);
-
- if(!(filter = CxFilter("rawmouse ctrl leftbutton lmouse")))
- Cleanup("Unable to create filter",RETURN_FAIL);
-
- SetFilterIX(filter,&ix);
-
- if(!(sender = CxSender(msgPort,CXID_SENDER1)))
- Cleanup("Unable to create sender",RETURN_FAIL);
-
- if(!(stripqual = CxCustom(CxStripQualifier,0)))
- Cleanup("Unable to create custom `CxStripQualifier'",RETURN_FAIL);
-
- AttachCxObj(broker,filter);
- AttachCxObj(filter,sender);
- AttachCxObj(filter,stripqual);
-
- { WORD quit=0;
- CxMsg *msg;
- WORD cx=0,cy=0,lx,ly,nx,ny;
- ULONG signal,msgid,msgtype,msgmask,brkmask,waitmask;
- struct InputEvent ie;
- struct Window *aw,*lw;
-
- msgmask = 1 << msgPort->mp_SigBit;
- brkmask = SIGBREAKF_CTRL_C;
- waitmask = msgmask | brkmask;
-
- ActivateCxObj(broker,1);
-
- while(!quit)
- {
- signal = Wait(waitmask);
-
- if(signal & msgmask){
- while(msg = (CxMsg *) GetMsg(msgPort))
- {
- msgid = CxMsgID(msg);
- msgtype = CxMsgType(msg);
- if(msgtype == CXM_IEVENT)
- ie = *((struct InputEvent *) CxMsgData(msg));
-
- ReplyMsg((struct Message *) msg);
-
- switch(msgtype)
- {
- case CXM_IEVENT:
- if(msgid == CXID_SENDER1)
- {
- if(!(ie.ie_Qualifier &
- (~(ix.ix_Qualifier | 0x8c00))))
- { aw = IntuitionBase->ActiveWindow;
- /* only drag dragable windows! */
- if(aw->Flags & WFLG_DRAGBAR)
- {
- nx = aw->WScreen->MouseX - (aw->Width>>1);
- ny = aw->WScreen->MouseY - (aw->Height>>1);
- /* Move window only if to new pos. */
- if(!((aw == lw) &&
- (nx == lx) && (ny == ly)))
- {
- MoveWindow(aw,
- nx - aw->LeftEdge,ny-aw->TopEdge);
- }
- lx = nx; ly = ny; lw = aw;
- }
- }
- }
- break;
-
- case CXM_COMMAND:
- switch(msgid)
- {
- case CXCMD_DISABLE:
- ActivateCxObj(broker,0);
- break;
- case CXCMD_ENABLE:
- ActivateCxObj(broker,1);
- break;
- /* If run twice or CX said so, die */
- case CXCMD_UNIQUE:
- case CXCMD_KILL:
- quit = 1;
- break;
- }
- break;
- }
- }}
- else if(signal & brkmask)
- quit = 1;
- }
- }
-
- Cleanup(NULL,0);
- }
-
- /* This my Custom CX object. As a CxTranslate(NULL) couldn't be used (it
- stripped off the mouse movements), I need this to simply strip off the
- qualifiers & codes allowing intuition to move the pointer. */
- __geta4 void CxStripQualifier(CxMsg *cxm,CxObj *co)
- {
- struct InputEvent *ie;
-
- ie = (struct InputEvent *) CxMsgData(cxm);
-
- /* Only remove when I am dragging - using same critera. */
- if(!(ie->ie_Qualifier & ~(ix.ix_Qualifier | 0x8c00)))
- { ie->ie_Qualifier = 0;
- ie->ie_Code = 0;
- }
- }
-
- /* Cleans up, no matter what */
- void Cleanup(char *errStr,ULONG errNum)
- {
- if(stripqual)
- DeleteCxObj(stripqual);
- if(sender)
- DeleteCxObj(sender);
- if(filter)
- DeleteCxObj(filter);
- if(broker)
- DeleteCxObj(broker);
- if(msgPort)
- DeletePort(msgPort);
- if(CxBase)
- CloseLibrary(CxBase);
- if(rdArgs)
- FreeArgs(rdArgs);
- if(IconBase)
- CloseLibrary(IconBase);
-
- if(errStr)
- {
- if(FromWB)
- {
- if(!IntuitionBase)
- IntuitionBase = (struct IntuitionBase *) OpenLibrary("intuition.library",36l);
-
- if(IntuitionBase)
- EasyRequest(NULL,&ez,NULL,errStr);
- }
- else
- printf("RealDrag: %s\n",errStr);
- }
-
- if(IntuitionBase)
- CloseLibrary((struct Library *)IntuitionBase);
-
- exit(errNum);
- }
-