/* $Revision Header * Header built automatically - do not edit! ************* * * (C) Copyright 1990 by Olaf Barthel & MXM * * Name .....: FracBlank.c * Created ..: Friday 18-Jun-91 15:28 * Revision .: 3 * * Date Author Comment * ========= ======== ==================== * 29-Jun-91 Olsen Added VBlank interrupt server. * 21-Jun-91 Olsen Optimizations, cleanups. * 18-Jun-91 Olsen Created this file! * * $Revision Header ********************************************************/ /* Include the specific math pragmas/header files here (is there * any way to figure this out by taking a look at predefined * compiler symbols?). */ #ifdef MATH_FFP #include #include #include #else #include #endif /* MATH_FFP */ #include /* sin -45° = cos -45° (saves precious calculation time). */ #define deg45 -0.707106781 /* Hotkey IDs. */ enum { POP_WINDOW,BLANK_SCREEN }; /* Gadget IDs. */ enum { GAD_SCREENTIMEOUT,GAD_PATTERNCHANGE,GAD_HOTKEY, GAD_BLANKSCREEN,GAD_HIDE,GAD_QUIT }; /* Dimensions of the control panel. */ #define WIDTH 308 #define HEIGHT 87 /* Sprite blanker interface data. */ struct BlankerInfo { struct Task *RingBack; BYTE Signal; BYTE Enabled; }; /* Program revision tag. */ STATIC const UBYTE * const VersTag = "\0$VER: FracBlank 1.4 (23.7.91)"; /* Shared library identifiers. */ extern struct ExecBase *SysBase; struct IntuitionBase *IntuitionBase; struct GfxBase *GfxBase; struct Library *CxBase, *IconBase, *GadToolsBase; /* Blanker data. */ struct Task *BlankTask; struct Screen *BlankScreen; /* Commodities interface data. */ struct MsgPort *CxPort; CxObj *Broker; /* Gfx and gadtools data. */ struct Screen *DefaultScreen; APTR VisualInfo; struct TextFont *Topaz; struct Gadget *GadgetList; struct Gadget *GadgetArray[6]; struct Window *Window; /* Rainbow colour table. */ UWORD Table[75]; /* Key sequence buffers. */ UBYTE HotkeyBuffer[256],BlankScreenBuffer[256]; /* Screen and pattern change timeout. */ ULONG ScreenCount = 0,PatternCount = 0,ScreenTimeout,PatternTimeout; /* The default font to be used by the control panel. */ struct TextAttr DefaultFont = { (UBYTE *)"topaz.font", 8, FS_NORMAL, FPF_ROMFONT }; /* A new broker definition, Commodities needs this. */ struct NewBroker NewBroker = { NB_VERSION, "FracBlanker", "Fractal Blanker v1.3", "Screen Blanker", NBU_NOTIFY | NBU_UNIQUE, 0,0,NULL,0 }; /* Function prototypes. */ extern VOID __asm Plot(register __a0 PLANEPTR Plane,register __d0 UWORD x,register __d1 UWORD y,register __d2 UWORD Modulo,register __d3 UWORD MaxX,register __d4 UWORD MaxY); LONG __saveds ShowTime(struct Gadget *SomeGadget,WORD Level); struct Gadget * CreateAllGadgets(struct Gadget **GadgetArray,struct Gadget **GadgetList,APTR VisualInfo,UWORD TopEdge); VOID ShutdownWindow(VOID); BYTE SetupWindow(VOID); LONG __saveds __asm SpriteBlanker(register __a1 struct BlankerInfo *BlankerInfo); VOID SpriteSwitch(BYTE Enabled); VOID __saveds BlankerAction(CxMsg *CxMessage,CxObj *CxObject); VOID ShutdownCx(VOID); BYTE SetupCx(UBYTE **ToolTypes); VOID HandleCxMsg(CxMsg *Message); ULONG Random(ULONG MaxValue); VOID __saveds Blanker(VOID); VOID CloseAll(LONG ReturnCode); VOID OpenAll(int argc,char **argv); VOID __stdargs main(int argc,char **argv); /* ShowTime(struct Gadget *SomeGadget,WORD Level): * * Gadtools support routine, displays the timeouts. */ LONG __saveds ShowTime(struct Gadget *SomeGadget,WORD Level) { STATIC UBYTE Buffer[30]; if(Level) SPrintf(Buffer,"%2ld.%02ld",Level / 60,Level % 60); else SPrintf(Buffer,"-Off-"); return((LONG)Buffer); } /* CreateAllGadgets(): * * Gadtools support routine, creates all the gadgets * required by the control panel. */ struct Gadget * CreateAllGadgets(struct Gadget **GadgetArray,struct Gadget **GadgetList,APTR VisualInfo,UWORD TopEdge) { struct Gadget *Gadget; struct NewGadget NewGadget; UWORD Counter = 0; if(Gadget = CreateContext(GadgetList)) { NewGadget . ng_Width = 104; NewGadget . ng_Height = 12; NewGadget . ng_GadgetText = "_Screen Timeout "; NewGadget . ng_TextAttr = &DefaultFont; NewGadget . ng_VisualInfo = VisualInfo; NewGadget . ng_GadgetID = Counter; NewGadget . ng_Flags = 0; NewGadget . ng_LeftEdge = (strlen(NewGadget . ng_GadgetText) + 2 - 1) * 8 + 2; NewGadget . ng_TopEdge = 1 + TopEdge; GadgetArray[Counter++] = Gadget = CreateGadget(SLIDER_KIND,Gadget,&NewGadget, GT_Underscore, '_', GTSL_Min, 0, GTSL_Max, 30 * 60, GTSL_Level, ScreenTimeout, GTSL_DispFunc, ShowTime, GTSL_LevelFormat, "%s", GTSL_MaxLevelLen, 5, TAG_DONE); NewGadget . ng_GadgetText = "_Pattern Change "; NewGadget . ng_GadgetID = Counter; NewGadget . ng_TopEdge = Gadget -> TopEdge + Gadget -> Height + 3; GadgetArray[Counter++] = Gadget = CreateGadget(SLIDER_KIND,Gadget,&NewGadget, GT_Underscore, '_', GTSL_Min, 0, GTSL_Max, 30 * 60, GTSL_Level, PatternTimeout, GTSL_DispFunc, ShowTime, GTSL_LevelFormat, "%s", GTSL_MaxLevelLen, 5, TAG_DONE); NewGadget . ng_GadgetText = "Hot _Key"; NewGadget . ng_GadgetID = Counter; NewGadget . ng_Height = 14; NewGadget . ng_TopEdge = Gadget -> TopEdge + Gadget -> Height + 3; GadgetArray[Counter++] = Gadget = CreateGadget(STRING_KIND,Gadget,&NewGadget, GT_Underscore, '_', GTST_MaxChars, 256, GTST_String, HotkeyBuffer, TAG_DONE); NewGadget . ng_GadgetText = "_Blank Screen"; NewGadget . ng_GadgetID = Counter; NewGadget . ng_Height = 14; NewGadget . ng_TopEdge = Gadget -> TopEdge + Gadget -> Height + 4; GadgetArray[Counter++] = Gadget = CreateGadget(STRING_KIND,Gadget,&NewGadget, GT_Underscore, '_', GTST_MaxChars, 256, GTST_String, BlankScreenBuffer, TAG_DONE); NewGadget . ng_GadgetText = "_Hide"; NewGadget . ng_GadgetID = Counter; NewGadget . ng_Flags = 0; NewGadget . ng_LeftEdge = 10; NewGadget . ng_TopEdge = HEIGHT - 3 - NewGadget . ng_Height; GadgetArray[Counter++] = Gadget = CreateGadget(BUTTON_KIND,Gadget,&NewGadget, GT_Underscore, '_', TAG_DONE); NewGadget . ng_GadgetText = "_Quit"; NewGadget . ng_GadgetID = Counter; NewGadget . ng_LeftEdge = WIDTH - 10 - NewGadget . ng_Width; GadgetArray[Counter++] = Gadget = CreateGadget(BUTTON_KIND,Gadget,&NewGadget, GT_Underscore, '_', TAG_DONE); } return(Gadget); } /* ShutdownWindow(): * * Closes the control panel. */ VOID ShutdownWindow() { if(Window) { CloseWindow(Window); Window = NULL; } if(GadgetList) { FreeGadgets(GadgetList); GadgetList = NULL; } if(VisualInfo) { FreeVisualInfo(VisualInfo); VisualInfo = NULL; } if(DefaultScreen) { UnlockPubScreen(NULL,DefaultScreen); DefaultScreen = NULL; } if(Topaz) { CloseFont(Topaz); Topaz = NULL; } } /* SetupWindow(): * * Creates the control panel and disables the screen * blanker. */ BYTE SetupWindow() { if(BlankTask) { RemTask(BlankTask); BlankTask = NULL; } if(BlankScreen) { ScreenToBack(BlankScreen); CloseScreen(BlankScreen); BlankScreen = NULL; SpriteSwitch(TRUE); } if(Window) return(TRUE); if(Topaz = (struct TextFont *)OpenFont(&DefaultFont)) { if(DefaultScreen = (struct Screen *)LockPubScreen(NULL)) { if(VisualInfo = GetVisualInfo(DefaultScreen,TAG_DONE)) { if(CreateAllGadgets(&GadgetArray[0],&GadgetList,VisualInfo,DefaultScreen -> WBorTop + DefaultScreen -> Font -> ta_YSize + 1)) { if(Window = OpenWindowTags(NULL, WA_Width, WIDTH, WA_Height, HEIGHT + DefaultScreen -> Font -> ta_YSize - 8, WA_Activate, TRUE, WA_DragBar, TRUE, WA_DepthGadget, TRUE, WA_CloseGadget, TRUE, WA_RMBTrap, TRUE, WA_IDCMP, IDCMP_CLOSEWINDOW | IDCMP_VANILLAKEY | SLIDERIDCMP | BUTTONIDCMP, WA_Title, "Fractal Blanker v1.3", TAG_DONE)) { SetFont(Window -> RPort,Topaz); AddGList(Window,GadgetList,(UWORD)-1,(UWORD)-1,NULL); RefreshGList(GadgetList,Window,NULL,(UWORD)-1); GT_RefreshWindow(Window,NULL); return(TRUE); } } } } } ShutdownWindow(); return(FALSE); } /* SpriteBlanker(): * * VBlank interrupt server, turns on/off all sprite channels * at the top of the frame. */ LONG __saveds __asm SpriteBlanker(register __a1 struct BlankerInfo *BlankerInfo) { /* Are we still to run this piece of code? */ if(BlankerInfo -> RingBack) { /* Enabled/disable the sprites. */ if(BlankerInfo -> Enabled) ON_SPRITE else { UWORD i; OFF_SPRITE for(i = 0 ; i < 8 ; i++) { custom . spr[i] . dataa = 0; custom . spr[i] . datab = 0; } } /* Signal father task to remove the server. */ Signal(BlankerInfo -> RingBack,1 << BlankerInfo -> Signal); /* Sprites are to be turned on only once. */ if(BlankerInfo -> Enabled) BlankerInfo -> RingBack = NULL; } return(0); } /* SpriteSwitch(BYTE Enabled): * * Enable/disable sprite DMA by enabling a VBlank * interrupt server. */ VOID SpriteSwitch(BYTE Enabled) { struct BlankerInfo __aligned BlankerInfo; struct Interrupt __aligned BlankInterrupt; /* Fill in the standard data. */ BlankerInfo . RingBack = SysBase -> ThisTask; BlankerInfo . Signal = AllocSignal(-1); BlankerInfo . Enabled = Enabled; /* Did we get the a signal? */ if(BlankerInfo . Signal != -1) { /* Enable the interrupt server. */ BlankInterrupt . is_Node . ln_Name = "FracBlank.interrupt"; BlankInterrupt . is_Node . ln_Type = NT_INTERRUPT; BlankInterrupt . is_Node . ln_Pri = 0; BlankInterrupt . is_Code = (APTR)SpriteBlanker; BlankInterrupt . is_Data = (APTR)&BlankerInfo; WaitTOF(); WaitTOF(); AddIntServer(INTB_VERTB,&BlankInterrupt); /* Wait for ringback signal. */ Wait(1 << BlankerInfo . Signal); if(!Enabled) { /* Wait for another signal to make sure the * sprites are really off. */ Wait(1 << BlankerInfo . Signal); } /* Remove the server. */ RemIntServer(INTB_VERTB,&BlankInterrupt); /* Free the signal. */ FreeSignal(BlankerInfo . Signal); } } /* BlankerAction(CxMsg *CxMessage,CxObj *CxObject): * * Commodities support routine, handles the Commodities * custom actions (in this case: filter the InputEvents * coming in and enable/disable the screen blanker). */ VOID __saveds BlankerAction(CxMsg *CxMessage,CxObj *CxObject) { STATIC BYTE Count = 1; struct InputEvent *Event = (struct InputEvent *)CxMsgData(CxMessage); /* Push the blanker screen to the front if necessary. */ if(BlankScreen) { if(BlankScreen -> TopEdge) MoveScreen(BlankScreen,0,-BlankScreen -> TopEdge); if(IntuitionBase -> FirstScreen != BlankScreen) { ScreenToFront(BlankScreen); SpriteSwitch(FALSE); } } /* This looks like a timer event. */ if(Event -> ie_Class == IECLASS_TIMER && !Window) { /* Screen blanker still inactive? */ if(!BlankTask) { /* Is there a timeout to take care of? */ if(ScreenTimeout) { /* Are we ready to create the * screenblanker? */ if(ScreenCount++ >= ScreenTimeout * 10) { if(BlankTask = (struct Task *)CreateTask("FracBlank.task",-20,Blanker,4000)) PatternCount = 0; } } } else { /* Every 5/60 second we signal the blanker * task to rotate the palette. */ if(Count++ == 2) { Signal(BlankTask,SIGBREAKF_CTRL_E); Count = 0; } /* Is it time to change the pattern? */ if(PatternTimeout) { if(PatternCount++ >= PatternTimeout * 10) { Signal(BlankTask,SIGBREAKF_CTRL_D); PatternCount = 0; } } } } else { /* The following line determines whether * the blanker is to be removed or to * be left running. */ if((Event -> ie_Class == IECLASS_RAWKEY && !(Event -> ie_Code & IECODE_UP_PREFIX)) || Event -> ie_Class == IECLASS_RAWMOUSE) { /* Remove the blanker task. */ if(BlankTask) { RemTask(BlankTask); BlankTask = NULL; } /* Close the blanker screen. */ if(BlankScreen) { ScreenToBack(BlankScreen); SpriteSwitch(TRUE); CloseScreen(BlankScreen); BlankScreen = NULL; } } ScreenCount = 0; } } /* ShutdownCx(): * * Close the Commodities interface. */ VOID ShutdownCx() { if(CxPort) { struct Message *Message; /* Remove the broker. */ if(Broker) DeleteCxObjAll(Broker); /* Remove the MsgPort from the public list. */ RemPort(CxPort); /* Remove all pending messages. */ while(Message = GetMsg(CxPort)) ReplyMsg(Message); /* Delete the MsgPort. */ DeleteMsgPort(CxPort); CxPort = NULL; Broker = NULL; } } /* SetupCx(UBYTE **ToolTypes): * * Set up the Commodities interface. */ BYTE SetupCx(UBYTE **ToolTypes) { /* Cancel any previously made assignments. */ ShutdownCx(); /* Create a reply port. */ if(CxPort = CreateMsgPort()) { /* Fill in a unique name. */ CxPort -> mp_Node . ln_Name = NewBroker . nb_Name; /* Add the reply port to the public list. */ AddPort(CxPort); /* Set the Commodity priority if possible. */ if(ToolTypes) { NewBroker . nb_Pri = ArgInt(ToolTypes,"CX_PRIORITY",0); NewBroker . nb_Port = CxPort; } /* This Commodity features a control panel. */ NewBroker . nb_Flags |= COF_SHOW_HIDE; /* Create the broker. */ if(Broker = CxBroker(&NewBroker,NULL)) { CxObj *ObjectList; UBYTE *String; /* Set the Commodity popup hotkey if possible. */ if(ToolTypes) { String = ArgString(ToolTypes,"CX_POPKEY","shift f1"); strcpy(HotkeyBuffer,String); } /* Link the hotkey. */ AttachCxObj(Broker,HotKey(HotkeyBuffer,CxPort,POP_WINDOW)); /* Determine the screen blanker hotkey. */ if(ToolTypes) { String = ArgString(ToolTypes,"BLANKSCREEN","shift f2"); strcpy(BlankScreenBuffer,String); } /* Link another hotkey. */ AttachCxObj(Broker,HotKey(BlankScreenBuffer,CxPort,BLANK_SCREEN)); /* Adjust the screen timeout if possible. */ if(ToolTypes) ScreenTimeout = ArgInt(ToolTypes,"SCREENTIMEOUT",60); /* Adjust the pattern change timeout if possible. */ if(ToolTypes) PatternTimeout = ArgInt(ToolTypes,"PATTERNTIMEOUT",60); /* Install the plain InputEvent handler. */ ObjectList = CxCustom(BlankerAction,NULL); /* Any accumulated errors? */ if(!CxObjError(ObjectList)) { /* Add the custom object. */ AttachCxObj(Broker,ObjectList); /* Any errors? */ if(!CxObjError(Broker)) { /* Activate the broker. */ ActivateCxObj(Broker,TRUE); return(TRUE); } } } } ShutdownCx(); return(FALSE); } /* HandleCxMsg(CxMsg *Message): * * Handle incoming Commodities messages. */ VOID HandleCxMsg(CxMsg *Message) { ULONG MessageType = CxMsgID(Message),MessageID = CxMsgType(Message); ReplyMsg((struct Message *)Message); /* Take a look at the message type. */ switch(MessageID) { /* It's a hotkey. */ case CXM_IEVENT: switch(MessageType) { /* Create the control panel. */ case POP_WINDOW: SetupWindow(); break; /* Blank the screen. */ case BLANK_SCREEN: if(!BlankTask) { /* Blanker task isn't running yet, * so let's create it. */ if(BlankTask = (struct Task *)CreateTask("FracBlank.task",-20,Blanker,4000)) PatternCount = 0; } else { /* Tell the blanker task to change the pattern. */ Signal(BlankTask,SIGBREAKF_CTRL_D); PatternCount = 0; } break; } break; /* It's an internal Commodities command. */ case CXM_COMMAND: switch(MessageType) { /* Disable the Commodity. */ case CXCMD_DISABLE: ActivateCxObj(Broker,FALSE); break; /* Enable the Commodity. */ case CXCMD_ENABLE: ActivateCxObj(Broker,TRUE); break; /* Create the control panel. */ case CXCMD_APPEAR: case CXCMD_UNIQUE: SetupWindow(); break; /* Close the control panel. */ case CXCMD_DISAPPEAR: ShutdownWindow(); break; /* Remove this Commodity. */ case CXCMD_KILL: CloseAll(RETURN_OK); break; } break; } } /* Random(ULONG MaxValue): * * Simple random number generation routine. */ ULONG Random(ULONG MaxValue) { STATIC ULONG RandomSeed = 0xDEAD0123; RandomSeed = RandomSeed * custom . vhposr + 0xE153766F; return(RandomSeed % MaxValue); } /* Blanker(): * * The screen blanker itself. */ VOID __saveds Blanker() { /* Open the screen. */ if(BlankScreen = OpenScreenTags(NULL, SA_Behind, TRUE, SA_Quiet, TRUE, SA_DisplayID, HIRESLACE_KEY, SA_Overscan, OSCAN_STANDARD, SA_Depth, 1, TAG_DONE)) { STATIC BYTE Wheel = 0; UWORD Modulo = BlankScreen -> RastPort . BitMap -> BytesPerRow,Colours[2],OffsetX = BlankScreen -> Width >> 1,OffsetY = BlankScreen -> Height >> 1; PLANEPTR Plane = BlankScreen -> RastPort . BitMap -> Planes[0]; float x = 0,y = 0,yy,a,b,c,sx,sy,mag,save; /* Provide starting numbers for the fractal * parameters. */ a = (float)Random(300) / 100; b = (float)Random(100) / 100; c = (float)Random( 50) / 100; mag = (float)(1 << (Random(4) + 5)) * deg45; /* Set up the screen colour table. */ Colours[0] = 0; Colours[1] = Table[Wheel]; LoadRGB4(&BlankScreen -> ViewPort,Colours,2); /* Push the screen to the front. */ ScreenToFront(BlankScreen); /* Turn off all sprite channels. */ SpriteSwitch(FALSE); /* Go into fractal generation loop. */ FOREVER { /* The original formula looks like * this: * ½ * x <- y - SIGN(x) * ABS(b * x - c) * y <- a - x * * I have split the calculation into * several steps to save time and * variables. */ yy = a - x; if((save = b * x - c) < 0) save = -save; if(x < 0) x = y + sqrt(save); else x = y - sqrt(save); y = yy; /* The resulting image appears to have * been rotated by 45°, so we'll * rotate the pixel coordinates by -45° * * x <- x * cos alpha + y * sin alpha * y <- -x * sin alpha + y * cos alpha * * We also magnify the image (i.e. the * distribution of pixels) in the following * lines. */ sx = mag * ( x + y); sy = mag * (-x + y); /* If the pixel happens to reside within * the boundaries of the screen, draw it. */ Plot(Plane,(LONG)(sx) + OffsetX,(LONG)(sy) + OffsetY,Modulo,BlankScreen -> Width,BlankScreen -> Height); /* ^D tells the blanker to change the pattern. */ if(SetSignal(0,0) & SIGBREAKF_CTRL_D) { SetSignal(0,SIGBREAKF_CTRL_D); SetRast(&BlankScreen -> RastPort,0); x = y = 0; a = (float)Random(300) / 100; b = (float)Random(100) / 100; c = (float)Random( 50) / 100; mag = (float)(1 << (Random(4) + 5)) * deg45; } /* ^E tells the blanker to rotate the * colours. */ if(SetSignal(0,0) & SIGBREAKF_CTRL_E) { SetSignal(0,SIGBREAKF_CTRL_E); Wheel = (Wheel + 1) % 75; Colours[1] = Table[Wheel]; LoadRGB4(&BlankScreen -> ViewPort,Colours,2); } } } /* Quietly remove ourselves. */ Forbid(); BlankTask = NULL; RemTask(SysBase -> ThisTask); } /* CloseAll(LONG ReturnCode): * * Free all resources and exit the program. */ VOID CloseAll(LONG ReturnCode) { if(CxBase && IconBase) { ShutdownCx(); ArgArrayDone(); } if(BlankTask) RemTask(BlankTask); if(BlankScreen) { SpriteSwitch(TRUE); ScreenToBack(BlankScreen); CloseScreen(BlankScreen); } ShutdownWindow(); if(IconBase) CloseLibrary(IconBase); if(CxBase) CloseLibrary(CxBase); if(GadToolsBase) CloseLibrary(GadToolsBase); if(GfxBase) CloseLibrary(GfxBase); if(IntuitionBase) CloseLibrary(IntuitionBase); exit(ReturnCode); } /* OpenAll(int argc,char **argv): * * Open all resources, initialize the colour table and * create the Commodities interface. */ VOID OpenAll(int argc,char **argv) { UBYTE **ToolTypes,*String; SHORT i,c = 0,r = 15,g = 0,b = 0; /* Create a table of rainbow colours. */ for(i = 0 ; i < 16 ; i++) Table[c++] = (r << 8) | ((g++) << 4) | b; g = 15; r--; for(i = 0 ; i < 15 ; i++) Table[c++] = ((r--) << 8) | (g << 4) | b; r = 0; g--; b++; for(i = 0 ; i < 15 ; i++) Table[c++] = (r << 8) | ((g--) << 4) | (b++); g = 0; b = 15; r++; for(i = 0 ; i < 15 ; i++) Table[c++] = ((r++) << 8) | (g << 4) | b; r = 15; b--; for(i = 0 ; i < 14 ; i++) Table[c++] = (r << 8) | (g << 4) | (b--); /* Open the libraries we need. */ if(!(IntuitionBase = (struct IntuitionBase *)OpenLibrary("intuition.library",37))) CloseAll(RETURN_FAIL + 0); if(!(GfxBase = (struct GfxBase *)OpenLibrary("graphics.library",37))) CloseAll(RETURN_FAIL + 1); if(!(GadToolsBase = OpenLibrary("gadtools.library",37))) CloseAll(RETURN_FAIL + 2); if(!(CxBase = OpenLibrary("commodities.library",37))) CloseAll(RETURN_FAIL + 3); if(!(IconBase = OpenLibrary("icon.library",37))) CloseAll(RETURN_FAIL + 4); /* Parse the startup arguments. */ ToolTypes = ArgArrayInit(argc,argv); /* Provide default values. */ strcpy(HotkeyBuffer, "shift f1"); strcpy(BlankScreenBuffer, "shift f2"); ScreenTimeout = 60; PatternTimeout = 60; /* Create the commodities interface. */ if(!SetupCx(ToolTypes)) CloseAll(RETURN_FAIL + 5); /* Pop up the control panel if necessary. */ if(ToolTypes) { String = ArgString(ToolTypes,"CX_POPUP","no"); if(!strcmpi(String,"yes") || !strcmpi(String,"on")) SetupWindow(); } } /* main(int argc,char **argv): * * That's where all the trouble starts. */ VOID __stdargs main(int argc,char **argv) { ULONG SignalSet; /* Open everything we need. */ OpenAll(argc,argv); /* Go into loop waiting for messages. */ FOREVER { SignalSet = (1 << CxPort -> mp_SigBit) | SIGBREAKF_CTRL_E; /* If the window is still open, wait for * some news. */ if(Window) SignalSet |= (1 << Window -> UserPort -> mp_SigBit); SignalSet = Wait(SignalSet); /* There are messages pending at the * Commodities reply port. */ if(SignalSet & (1 << CxPort -> mp_SigBit)) { CxMsg *Message; while(Message = (CxMsg *)GetMsg(CxPort)) HandleCxMsg(Message); } /* ^E tells the program to quit. */ if(SignalSet & SIGBREAKF_CTRL_E) CloseAll(RETURN_OK); /* If the control panel is still open, * check for new messages. */ if(Window) { if(SignalSet & (1 << Window -> UserPort -> mp_SigBit)) { struct IntuiMessage *Massage; struct Gadget *Gadget; ULONG Class,Code; while(Massage = (struct IntuiMessage *)GT_GetIMsg(Window -> UserPort)) { Class = Massage -> Class; Code = Massage -> Code; Gadget = (struct Gadget *)Massage -> IAddress; GT_ReplyIMsg(Massage); switch(Class) { /* Close the window. */ case IDCMP_CLOSEWINDOW: ShutdownWindow(); break; /* Set the slider values. */ case IDCMP_MOUSEMOVE: switch(Gadget -> GadgetID) { case GAD_SCREENTIMEOUT: ScreenCount = 0; ScreenTimeout = Code; break; case GAD_PATTERNCHANGE: PatternCount = 0; PatternTimeout = Code; break; } break; /* Handle the keyboard shortcuts. */ case IDCMP_VANILLAKEY: switch(toupper(Code)) { case 'S': ScreenCount = 0; if(Code == 's') { if(ScreenTimeout + 1 <= 30 * 60) ScreenTimeout++; else ScreenTimeout = ScreenTimeout + 1 - 30 * 60; } else { if(ScreenTimeout + 10 <= 30 * 60) ScreenTimeout += 10; else ScreenTimeout = ScreenTimeout + 10 - 30 * 60; } GT_SetGadgetAttrs(GadgetArray[GAD_SCREENTIMEOUT],Window,NULL, GTSL_Level,ScreenTimeout, TAG_DONE); break; case 'P': PatternCount = 0; if(Code == 'p') { if(PatternTimeout + 1 <= 30 * 60) PatternTimeout++; else PatternTimeout = PatternTimeout + 1 - 30 * 60; } else { if(PatternTimeout + 10 <= 30 * 60) PatternTimeout += 10; else PatternTimeout = PatternTimeout + 10 - 30 * 60; } GT_SetGadgetAttrs(GadgetArray[GAD_PATTERNCHANGE],Window,NULL, GTSL_Level,PatternTimeout, TAG_DONE); break; case 'K': ActivateGadget(GadgetArray[GAD_HOTKEY],Window,NULL); break; case 'B': ActivateGadget(GadgetArray[GAD_BLANKSCREEN],Window,NULL); break; case 'H': ShutdownWindow(); break; case 'Q': CloseAll(RETURN_OK); default: break; } break; /* Handle the gadgets themselves. */ case IDCMP_GADGETUP: switch(Gadget -> GadgetID) { case GAD_HOTKEY: strcpy(HotkeyBuffer,((struct StringInfo *)Gadget -> SpecialInfo) -> Buffer); if(!SetupCx(NULL)) CloseAll(RETURN_FAIL + 5); break; case GAD_BLANKSCREEN: strcpy(BlankScreenBuffer,((struct StringInfo *)Gadget -> SpecialInfo) -> Buffer); if(!SetupCx(NULL)) CloseAll(RETURN_FAIL + 5); break; case GAD_HIDE: ShutdownWindow(); break; case GAD_QUIT: CloseAll(RETURN_OK); } break; } /* Window has been closed, do not * continue requesting messages * from the UserPort. */ if(!Window) break; } } } } }