/* * * Copywrite (C) 1986 by Davide P. Cervone * * Permission is granted for any individual or institution to use, * copy, or redistribute this software, provided this copywrite * notice is retained. * */ #include "exec/types.h" #include "exec/devices.h" #include "libraries/dos.h" #include "intuition/intuition.h" #include "graphics/gfxbase.h" #include "graphics/regions.h" #include "graphics/copper.h" #include "graphics/gels.h" #include "devices/keymap.h" #include "hardware/blit.h" #include "mxgadget.h" #define USERDATA(x) ((struct MxGadgetMasks *) x->UserData) SelectGadget(theGadget,theWindow,theRequester) struct Gadget *theGadget; struct Window *theWindow; struct Requester *theRequester; { if (isMxGadget(theGadget)) { struct MxGadgetMasks *theData = USERDATA(theWindow); LONG Exclude = theGadget->MutualExclude; /* Groups this gadget excludes */ LONG Disable = 0; /* Groups this gadget disables */ LONG Enable = 0; /* Groups this gadget enables */ if (theData != NULL && Exclude != 0) { if (MxFlagSet(theGadget,MXENABLEGADG)) Enable = Exclude & theData->EnableMask; if (MxFlagSet(theGadget,MXDISABLEGADG)) Disable = Exclude & theData->DisableMask; Exclude &= ~(theData->EnableMask | theData->DisableMask); } /* * If the gadget already is selected, just mutual exclude other gadgets; * Otherwise, if a TOGGLE gadget has just been unselected, then undo * any disabling or enabling caused when it was selected; * Otherwise, we are selecting a previously unselected, non-TOOGLE * gadget, so select it, draw its imagery, and mutual exclude others. */ if (isSelected(theGadget)) { ExcludeMxGadgets(theGadget,theWindow,theRequester, Exclude,Enable,Disable); } else { if (theGadget->Activation & TOGGLESELECT) { ExcludeMxGadgets(theGadget,theWindow,theRequester, 0,Disable,Enable); } else { SetGadgFlag(theGadget,SELECTED); DrawGadget(theGadget,theWindow,theRequester); ExcludeMxGadgets(theGadget,theWindow,theRequester, Exclude,Enable,Disable); } } } } UnSelectGadget(theGadget,theWindow,theRequester) struct Gadget *theGadget; struct Window *theWindow; struct Requester *theRequester; { /* * If the gadget is selected, then clear the selection flags; then, if it is * not disbaled, redraw it with unselected imagery. */ if (isAnySelected(theGadget)) { ClearGadgFlag(theGadget,SELECTED); ClearMxFlag(theGadget,MXSELECT); if (isNotDisabled(theGadget)) DrawGadget(theGadget,theWindow,theRequester); } } MxOffGadget(theGadget,theWindow,theRequester) struct Gadget *theGadget; struct Window *theWindow; struct Requester *theRequester; { /* * If the gadget currently is selected, save the status via the MXSELECT * flag so that when we enable the gadget again, we can re-select it. * Finally, "ghost" the gadget by turning it off. */ if (isSelected(theGadget) && isMxGadget(theGadget)) { ClearGadgFlag(theGadget,SELECTED); SetMxFlag(theGadget,MXSELECT); DrawGadget(theGadget,theWindow,theRequester); } IsolateGadget(theGadget,theWindow,theRequester); OffGadget(theGadget,theWindow,theRequester); RestoreGadget(theGadget,theWindow,theRequester); } MxOnGadget(theGadget,theWindow,theRequester) struct Gadget *theGadget; struct Window *theWindow; struct Requester *theRequester; { /* * Turn the gadget on, and if it was previously marked as SELECTED * (i.e., we saved the fact that it was selected via the MXSELECT flag), * then select the gadget and draw the selected imagery. */ IsolateGadget(theGadget,theWindow,theRequester); OnGadget(theGadget,theWindow,theRequester); RestoreGadget(theGadget,theWindow,theRequester); if (isMxGadget(theGadget) && isMxSelected(theGadget)) { SetGadgFlag(theGadget,SELECTED); ClearMxFlag(theGadget,MXSELECT); DrawGadget(theGadget,theWindow,theRequester); } } struct Window * MxOpenWindow(NewWindow) struct NewWindow *NewWindow; { struct Window *theWindow, *OpenWindow(); struct MxGadgetMasks *theData, *AllocMem(); /* * Open the window and allocate memory for the Enable/Diable masks for this * window. Since we are using the UserData pointer, supply another one, * so users have something to use. */ if ((theWindow = OpenWindow(NewWindow)) != NULL) { theData = AllocMem(sizeof(struct MxGadgetMasks),0); if (theData != NULL) { theData->DisableMask = 0; theData->EnableMask = 0; theData->UserData = NULL; theWindow->UserData = (BYTE *) theData; } } return(theWindow); } MxCloseWindow(theWindow) struct Window *theWindow; { /* * Free the mask data memory, and then close the window. */ if (theWindow != NULL) { if (theWindow->UserData != NULL) FreeMem(theWindow->UserData,sizeof(struct MxGadgetMasks)); CloseWindow(theWindow); } } SetMxGadgetMasks(theWindow,EnableMask,DisableMask) struct Window *theWindow; LONG EnableMask, DisableMask; { struct MxGadgetMasks *theData = USERDATA(theWindow); if (theData != NULL) { theData->DisableMask = DisableMask; theData->EnableMask = EnableMask; } } LONG GetMxGadgetMasks(theWindow,EnableMask,DisableMask) struct Window *theWindow; LONG *EnableMask, *DisableMask; { struct MxGadgetMasks *theData = USERDATA(theWindow); if (theData != NULL) { *DisableMask = theData->DisableMask; *EnableMask = theData->EnableMask; } else { *DisableMask = 0; *EnableMask = 0; } } DrawGadget(theGadget,theWindow,theRequester) struct Gadget *theGadget; struct Window *theWindow; struct Requester *theRequester; { LONG NotSelected = GadgFlagNotSet(theGadget,SELECTED); /* * If the gadget is not an IMAGE gadget (i.e., it uses complementation * to show that it is selected), then temporarily select it, so that we * are sure that complementation takes place. Refresh the gadget: for * IMAGE gadgets, the proper image is shown (selected or not), while for * non-IMAGE gadgets, this forces complementation (so that previously * selected gadgets become unselected, and vice versa). Finally, if the * gadget was not selected, clear the selected flag, and refresh non-IMAGE * gadgets again, to be sure that the border and text are shown in the * proper colors. Note that gadget borders and text should be rendered in * JAM1 mode, not COMPLEMENT mode. If you need to use COMPLEMENT mode, * remove the second RefreshGadgets call. */ if (GadgFlagNotSet(theGadget,GADGHIMAGE)) SetGadgFlag(theGadget,SELECTED); IsolateGadget(theGadget,theWindow,theRequester); RefreshGadgets(theGadget,theWindow,theRequester); if (NotSelected) { ClearGadgFlag(theGadget,SELECTED); if (GadgFlagNotSet(theGadget,GADGHIMAGE)) RefreshGadgets(theGadget,theWindow,theRequester); } RestoreGadget(theGadget,theWindow,theRequester); } static struct Gadget *FirstGadget = NULL; static struct Gadget *NextGadget = NULL; /* * When gadgets are mutually excluded, they are refreshed to show their * imagery properly selected or unselected. Unfortunately, refreshing * the complete gadget list toggles the displayed status for gadgets * that use GADGHCOMP or GADGHBOX selection. To avoid this, mutually * excluded gadgets are updated individually. First they are isolated * by making the gadget the only one in the window or requester gadget * list (the original pointers are stored in the two variable listed * above), then refreshed. Finally the gadget list is restored to its * original state using the saved pointers. This avoids the unwanted * toggling of COMP and BOX gadgets, and removes the annoying flicker * produced when IMAGE gadgets are refreshed unnecessarily. * * This is a little sneaky, but it should be relatively safe, since * it happens very quickly, and the integrity of the rest of the list is * not destroyed during the procedure. An alternate approach would be to * mark all the COMP and BOX gadgets in the list as being not SELECTED, * then do the refresh; finally, restore the SELECT flag to the proper * gadgets again. If you don't use COMP or BOX selection, then you can * remove the bodies of these two routines (just make them empty brackets). */ IsolateGadget(theGadget,theWindow,theRequester) struct Gadget *theGadget; struct Window *theWindow; struct Requester *theRequester; { NextGadget = theGadget->NextGadget; if (isReqGadg(theGadget)) { FirstGadget = theRequester->ReqGadget; theRequester->ReqGadget = theGadget; } else { FirstGadget = theWindow->FirstGadget; theWindow->FirstGadget = theGadget; } theGadget->NextGadget = NULL; } RestoreGadget(theGadget,theWindow,theRequester) struct Gadget *theGadget; struct Window *theWindow; struct Requester *theRequester; { theGadget->NextGadget = NextGadget; if (isReqGadg(theGadget)) theRequester->ReqGadget = FirstGadget; else theWindow->FirstGadget = FirstGadget; } ExcludeMxGadgets(theGadget,theWindow,theRequester,Exclude,Enable,Disable) struct Gadget *theGadget; struct Window *theWindow; struct Requester *theRequester; LONG Exclude, Enable, Disable; { struct Gadget *CheckGadget = (isReqGadg(theGadget)) ? theRequester->ReqGadget : theWindow->FirstGadget; LONG MutualExclude = Exclude | Enable | Disable; LONG CheckExclude; /* * Check each gadget in the window or requester list: * If it is excluded (or enabled or diabled) by the selected gadget, * and it is not the selected gadget then: * if it is selected and excluded then unselect it; * if it is an ON-OFF gadget (i.e., it can be enabled or disabled), then: * if it is disabled by the selected gadget and * it's not already disabled, then disable it; * if it is enabled by the selected gadget, and * it's currently disabled, then enable it. */ if (MutualExclude) { while (CheckGadget != NULL) { CheckExclude = CheckGadget->MutualExclude; if ((MutualExclude & CheckExclude) && (CheckGadget != theGadget)) { if (isAnySelected(CheckGadget) && (CheckExclude & Exclude)) UnSelectGadget(CheckGadget,theWindow,theRequester); if (MxFlagSet(CheckGadget,MXGADGONOFF)) { if ((CheckExclude & Disable) && (isNotDisabled(CheckGadget))) MxOffGadget(CheckGadget,theWindow,theRequester); if ((CheckExclude & Enable) && (isDisabled(CheckGadget))) MxOnGadget(CheckGadget,theWindow,theRequester); } } CheckGadget = CheckGadget->NextGadget; } } }